VBGood网站全文搜索 Google

搜索VBGood全站网页(全文搜索)
首页 - 经验之谈 - 用VB5 RDO访问数据库出现的缺陷及改正
发表评论(0)作者:, 平台:, 阅读:9863, 日期:2000-03-12


用VB5 RDO访问数据库出现的缺陷及改正



 当今,最流行的数据库管理系统是客户机/服务器系统。通常用VisualBasic(以下简称VB)作为应用程序的“前端”,MSSQLServer(以下简称SQLServer)作为“后端”来构成这一系统。

   在VB5.0企业版中有众多访问数据库的方法,如数据控件(Datacontrol)、数据访问对象(Dataaccessobject,DAO)、远程数据控件(Remotedatacontrol)、远程数据对象(Remotedataobjec,RDO)以及ODBCAPI等。其中,远程数据对象(RDO)在数据访问速度上可以与ODBCAPI匹敌,而在编程上不像直接调用ODBCAPI那么困难,在易用性和执行效率上达到了最佳平衡,因此,倍受VB程序员的青睐。


   但是,最近我们发现它在访问SQLServer时出现了一个缺陷,即在往SQLServer数据库中插入新的记录时,使得SQLServer的外键约束失效,同时也使参照表中的Checkconstraints部分失效,从而破坏了数据的参照完整。


   问题描述


   下面给出一个简单的显示RDO这一缺陷的实例程序。


   我们选择SQLServer6.5pubs数据库中的employee表来做这个实验,在初始状态下jobs中有14条记录(行),其中job_id字段(列)值分别为1~14;employee表中有43条记录,它的外键(Foreignkey)为jobs_id。数据的参照完整性要求employee表中的job_id字段值必须对应于jobs表中的job_id字段的某一个值,在employee表中加入一条新记录时,job_id的值也必须是jobs中的job_id的某一个值,否则,参照完整性就被破坏。


   实验步骤如下:


   首先,为pubs数据库在ODBC里创建一个数据源名称,这里假设为employees。在创建过程中指定服务器为SQLServer驻留的那台服务器,数据库名指定为pubs。


   再在VB5.0中建一个工程,设为Rdotest。为这个工程新建一个表格窗体Form1,表格上的组件及有关属性如右表所示。




对象 属性 设置

Form Name Form1

Caption Form1

Label Name Label1

Caption Emp_id

Label Name Label2

Caption Fname

Label Name Label3

Caption Fname

Label Name Label4

Caption Job_id

Label Name Label5

Caption Job_lv1

Caption Job_lv1

Label Name Text1

Text

Text Name Text2

Text

Text Name Text3

Text

Text Name Text4

Text

Text Name Text5

Text

Command Name C_add

Caption add

   在代码窗口中编写如下代码:

OptionExplicit


PrivaterdEnvAsrdoEnvironment


PrivaterdConnAsrdoConnection


PrivaterdRsAsrdoResultset




PrivateSubC_add_Click()


OnErrorGoTochkerr


rdRs.AddNew


rdRs(“emp_id”)=Text1.Text


rdRs(“fname”)=Text2.Text


rdRs(“lname”)=Text3.Text


rdRs(“job_id”)=Val(Text4.Text)


rdRs(“job_lvl”)=Val(Text5.Text)


rdRs.Update


ExitSub


chkerr:


MsgBoxErr.Description


ResumeNext


EndSub




PrivateSubForm_Load()


DimsSQLAsString


SetrdEnv=rdoEnvironments(0)


SetrdConn=rdEnv.OpenConnection(“employees”,_


rdDriverNoPrompt,False,“odbc;uid=sa;pwd=sa”)


sSQL=“select*fromemployee”


SetrdRs=rdConn.OpenResultset(sSQL,rdOpenKeyset,rdConcurRowVer,0)


EndSub



运行上述程序:


   在employee_id中输入aaalllllf,在fname中输入abc,在lname中输入ab,在job_id中输入15,在job_lvl中输入5。


   注意:这里job_id就不是jobs表中的任何一个job_id值:job_lvl中的值也不在其checkconstraints中应有的值,在jobs表的checkconstraints中要求job_lvl的值大于等于10,小于等于250。


   按add键后,程序往employee表中插入一个新记录,而且没有任何出错提示。


   再在SQLServer的ISQL/W程序中执行“Select*


   fromemployee”,会发现刚才所输入的内容的确加到了employee中,尽管job_id=15破坏了外键约束的条件。可见数据的完整性被破坏。


   解决方法


   为了防止这种情况的发生,可采用给数据库中每个有外键约束的表添加一个触发器的方法。以下给出一个简单的实例,仍以employee表及jobs表为例。


   我们给employee表加一个名为emp_insert的触发器:


CREATETRIGGERemp_insertONemployee


FORinsert


ASif(selectcount(*)fromjobs,inserted


wherejobs.job_id=inserted.job_id)=0


begin


print“inputjob_iderror!”


print“transactcann'tbeprocessed”


raiserror(50001,16,1)


rollbacktran


end