用vfp与sqlserver连接.docx
《用vfp与sqlserver连接.docx》由会员分享,可在线阅读,更多相关《用vfp与sqlserver连接.docx(63页珍藏版)》请在冰豆网上搜索。
用vfp与sqlserver连接
用vfp与sqlserver构建Client/Server应用程序(远程视图)
(1)
前言
VisualFoxPro为Client/Server构架的应用提供了两个内置的解决方案:
远程视图(RemoteViews)与SPT(SQLpassthrough)。
当然在VisualFoxPro中我们可以使用其它的远程数据连接的方法,比如ADO。
所有这些解决方案都各有优劣,远程视图最大的好处就是它可以非常方便地与VisualFoxPro内置控件绑定。
每一个远程视图就是一个存储于VisualFoxPro数据库容器(DBC)的对象,是一句SQL-SELECT语句。
远程视图通过ODBC(OpenDatabaseConnectivity)与异构数据库通讯。
虽然本文的实例使用SQLServer作为后端数据库,但大家同样可以使用其它数据源作为后端数据库,例如Oracle,IBMDB2,Informix,Sybase,MicrosoftAccess,Excel,甚至是VisualFoxPro自己。
使用远程视图操作远程数据就像操作VisualFoxPro本地数据一般,以下我们将介绍这一伟大工具的初级应用。
连接-Connections
使用远程视图操作远程数据的第一步就是建立与远程数据源的通讯,这里有好几种方法可供选择,请注意所有这些方法都使用ODBC与远程数据连接。
这里有一个非常简单的远程视图,它的作用是:
读取Northwind数据库中Customers表的记录到远程视图Vcustomers中。
CREATESQLVIEWVcustomers;
REMOTECONNECTIONNorthwind;
ASSELECT*FromCustomers
*先别试用这条语句,因为连接还没有建立
在上述命令的第二行我们告诉VisualFoxPro使用连接Northwind与SQLServer通讯。
在运行上面的语句时,VisualFoxPro将在两个地方寻找这个连接:
1.当前数据库容器(DBC)中查看是否存在数据库“连接对象”——Northwind。
笔者称之为基于DSN的连接对象。
2.如果没有发现,VisualFoxPro将在客户机的OCBCDataSourceNames(DSNs)中查看是否存在连接Northwind。
笔者称之为DSN连接。
建立DSNs连接
建立连接的最快、最方便的方法是建立DSNs,您可以在控制面板中打开ODBC控制器,如图1。
图1.ODBCDataSourceAdministrator面板
我们发现有三种DSN连接:
用户型DSN、系统型DSN、文件型DSN。
其中用户型只对建立它的用户有效,譬如你以Administrator的身份登录系统并建立了一个用户DSN,那么除非你以Administrator登录系统否则你不能使用这一DSN;系统型则对当前用机器所有用户生效,无论你以什么身份登录系统;文件型DSN实际上是一个以DSN为后缀名的文本文件。
从VisualFoxPro的角度,笔者把这三种DSN分成两类:
1.用户型、系统型DSN。
它可以单独作为连接为远程视图使用;也可以作为“基于DSN连接对象”的基础,“基于DSN连接对象”依赖于用户型或是系统型DSN。
2.文件型DSN。
它不可以单独作为连接为远程视图使用;它可以为设计“基于字符串的连接对象”提供资料,但“基于字符串的连接对象”不依赖于文件型DSN。
我们先建立一个系统型DSN。
在ODBCDataSourceAdministrator面板中选中“SystemDSN”页,按“Add”键,再选择SQLServer驱动程序,按“完成”按钮。
出现图2。
图2.设定DSN的名称及服务器
这里我们选择“(local)”,注意如果系统将尝试连接目标服务器如果无法连接将报错,如果顺利的话您将看到图3的画面,要求选择用户认证方式,这里我们选择SQLServer与Windows混合认证方式,并输入登录SQLServer的用户名:
“sa”,口令为空。
图3.设定DSN的登录信息
如果顺利画面4将出现在屏幕上,这里有一个选项要特别的注意,就是选择目标数据库。
这里我们当然是选“Northwind”。
图4.设定DSN的登录数据库
废话就不多说了,如果一些顺利,这条叫“Northwind”的SystemDSN就建成了。
在VisualFoxPro的命令窗口中建立如下语句:
CREATEDATABASENorthwind
*建立本地数据库容器,存储数据库对象。
CREATESQLVIEWVCustomers;
REMOTECONNECTIONNorthwind;
ASSELECT*FROMCustomers
*建立远程视图,注意这个视图是数据库(DBC)的一个对象,所以必须先建立DBC
USEVCustomers
*打开远程视图
BROWSE
*浏览远程视图
建立数据库容器(DBC)中的“连接对象”
记得在前文我们讲过连接可以存在于两个地方,就是DSNs与DBC,那么DSN与基于DSN的连接对象有什么区别?
基于DSN的连接对象可以为数个远程视图共享,而DSN连接不可以。
我们知道,每一条与SQLServer的连接都是要收费的,共享连接就可以省钱;我们还知道,SQLServer管理每条连接大约要花去24K的内存空间,有人讲:
24K不多,但您别忘了SQLServer是服务器,不只是您一个人使用它——东一条连接、西一条连接——系统效率一定会受影响。
因此无论从开发成本还是系统工作效率的角度,共享连接都是开发人员必然的选择。
为了说明什么是共享连接,为了证明DSN连接不能为试图共享,我们做以下试验:
CREATESQLVIEWVOrders;
REMOTECONNECTIONNorthwindSHARE;
ASSELECT*FROMOrders
*新建一个远程视图,仍然使用名称为Northwind的DSN连接
DBSETPROP('VCustomers','View','ShareConnection',.T.)
USEVCustomersIN0
*打开刚才的那个视图
USEVOrdersIN0
*打开新建的远程视图
?
CURSORGETPROP("ConnectHandle","VCustomers")
*显示1
?
CURSORGETPROP("ConnectHandle","VOrders")
*显示2
*这两个远程视图(光标)的连接句柄不是同一个。
如果一条连接被共享了,那么这两个光标的连接句柄应是同一个数字;这两个视图虽然使用同一个DSN但实际上它们没有共享连接。
为了使用共享连接着一特性,我们建立“基于DSN的连接对象”:
CREATECONNECTIONNorthwindDATASOURCENorthwind
以上这条连接是建立在上面我们建立的DSN连接之上的,连接成为数据库容器的一个对象了。
但注意:
这种连接对象并不能摆脱DSN的控制,它的连接信息仍然存储在DSN中。
为了在视图间共享连接,我们必须设定设图的共享连接的属性,凡是参与共享连接的远程视图都必须具备共享连接的属性,否则共享连接还是不能实现。
设定共享连接的方法有两种:
1.建立视图设计使用关键字SHARE。
如:
CREATESQLVIEWVOrders;
REMOTECONNECTIONNorthwindSHARE;
ASSELECT*FROMOrders
2.设定已视图的ShareConnection的属性为.t.。
如:
DBSETPROP('VCustomers','View','ShareConnection',.T.)
为了证明连接共享的特性我们执行以下代码:
USEVCustomersIN0
USEVOrdersIN0
?
CURSORGETPROP("ConnectHandle","VCustomers")
*显示:
1
?
CURSORGETPROP("ConnectHandle","VOrders")
*显示:
1
我们已经学习了怎样建立“基于DSN的连接对象”,并了解了连接共享。
仔细思考,您也许会发现“基于DSN的连接对象”存在下列问题:
1.运行时(RUNTIME)的可控性差。
比如我们希望应用程序在不同的条件下使用不同的用户登录数据库服务器、或是不同的数据库,是不是要建立N个DSN以及N个“基于DSN的连接”?
太可怕了!
2.由于“基于DSN的连接”对DSN的依赖性很强,例如:
用户删除或是更改了DSN信息,那么我们应用程序就无法正常运行了!
为了解决以上问题,VisualFoxPro提出了“连接字符串的概念”。
笔者称之为:
基于字符串的连接。
一个连接字符串基本上包括五个主要内容:
ODBC驱动器、服务器、用户名、登录名、数据库。
(针对SQLServer而言)
CREATECONNECTIONNorthwind2;
CONNSTRING"DRIVER=SQL;UID=sa;DATABASE=Northwind;SERVER=(local);PWD="
用vfp与sqlserver构建Client/Server应用程序(远程视图)
(2)
通过工具建立连接
以上我们都是通过命令的方式建立连接,现在我们将使用VisualFoxPro提供的连接设计器建立连接。
上文我们讲到:
连接对象分为两类:
“基于DSN的连接对象”和“基于字符串的连接对象”。
图5:
1.在连接设计器中选择“数据源、用户标识、密码”就说明在建立“基于DSN的连接对象”,在“数据源”列表框中可选择当前可用的用户型、系统型DSN。
1.在连接设计器中选择“连接串”就说明在建立“基于字符串的连接对象”,为了快速、正确的设计连接字符串,我们可以打开文件型DSN参考,注意:
“基于字符串的连接对象”不依赖文件型DSN。
图5.连接设计器
连接属性的设定
从连接设计器的画面上我们可以发现很多连接属性,他们代表什么意思呢?
在讲述这些问题之前,我想告诉大家:
所有这些属性的设定都可以通过DBSETPROP()函数,所有这些属性值的获取都可以通过DBGETPROP()函数得到。
下面,我们简要介绍几个属性:
1.异步执行。
默认值为.F.。
同步执行是指:
通过连接传送到后端的命令会被一句一句地执行,前一句没有执行完毕后一句就不会被执行;而同步执行是指:
当通过连接发出命令后,不管后端是否完成并返回结果,客户端程序可以继续往下走。
2.超时间隔-空闲(分)。
默认值是0。
设定一个非0值时,一个连接如果在这段时间内没被使用,VisualFoxPro将使它休眠,再次使用该连接时VisualFoxPro会激活它。
注意使用该属性,因为它常常使您的应用程序产生不明不白的错误,如"Connectivityerror:
unabletoretrievespecificerrorinformation.Driverisprobablyoutofresources."实际上现在ODBC提供了POOL的功能,这些问题可由ODBC自行解决,我们不用操心。
3.超时间隔-连接(秒)。
默认值是0。
设定一个非0值时,指在这个时间段内VisualFoxPro将试图连接到服务器,如果不成功,VisualFoxPro将产生一个错误。
4.显示ODBC登录提示。
在应用程序中,我们总不希望有系统弹出登录窗口,这样于形象不利、于程序的安全性不利,特别是设计COM对象时,由于无人看护,更不希望登录窗口的弹出,VisualFoxPro为我们提供了三种选择,笔者经常使用“从不显示”。
5.显示错误信息。
如果设定为.t.,任何ODBC错误将以Messagebox窗口显示出来;反之,ODBC错误有用户自行处理。
显然我们基本上使用默认设置.f.。
提示:
在VisualFoxPro中很多关于数据处理方面的设定,(如:
setdelete)都是限于数据工作期的,而连接被激活后可以在多个数据工作期内公用。
远程视图
弱水三千,取一瓢饮——条件视图
在前文我们已经建立了两个远程视图,您也许发现这种整个把远程表读取过来的做法执行效果很好,其实不然。
我有两大理由:
1.设想如果后端表很大(Customers只有91条记录),有几万、几十万条记录,结果会这样?
2.设想如果网络用户很多,网路很繁忙,结果会怎样?
Client\Server设计的一个重要的课题就是使网络流量最小化,所以在设计远程视图时就要考虑这一解决问题。
我们的想法是使远程视图仅下载有必要的信息,这就叫:
弱水三千,取一瓢饮。
例如:
CREATESQLVIEWVCustomers
REMOTECONNECTIONNorthwindSHARE;
ASSELECT*FROMCustomers
WHEREcustomeridLIKE'ALFKI'
我们在WHERE子句中加入条件“customeridLIKE'ALFKI'”,现在我们发现只有一条记录从远端被下载。
您也与已经发现这中间的不足:
这个远程视图太死板了——只能为Customerid类似于'ALFKI'的记录提供服务,是不是可以把'ALFKI'作为一个参数,供使这个远程视图更灵活,服务面更广。
可以,VisualFoxPro支持这样的远程视图:
CREATESQLVIEWVCustomers;
REMOTECONNECTIONNorthwindSHARE;
ASSELECT*FROMCustomers;
WHEREcustomeridLIKEcCustomerID
如果您打开远程视图或对已打开的远程视图执行REQUERY()、REFRESH()函数,VisualFoxPro会查找是由存在名为cCustomerID的变量。
如果存在,VisualFoxPro自动把变量值填入远程视图的SQL语句中;如果变量不存在,VisualFoxPro将弹出如下窗口询问变量值。
在实际开发应用程序中,我们会经常实现设定远程视图参数,在需要其它信息时,改变参数值,再用REQUERY()函数刷新客户端的数据;远程视图参数不仅可以填入普通数据,还可以使用统配符,如下:
cCustomerID='ALFKI'
USEVcustomers
BROWSE
cCustomerID='%B%'
REQUERY('Vcustomers')
BROWSE
这里有以下问题点大家必须注意:
1.远程视图参数只能在WHERE字句中设定,其他的连接子句、分组字句、排序子句都不支持这一特性。
比如不可以出现Orderby?
cOrder。
(有传言说VisualFoxPro7支持参数加入排序子句,但笔者还未及尝试)。
2.一个远程视图可以设定多个参数。
实例见下面的代码。
3.远程视图的SELECT-SQL语句必须是以后端数据库的语法为标准。
例如,SQLServer以单引号确认字符串,而VisualFoxPro可使用双引号、方括号、单引号确认字符串,那么如下语句是错误:
CREATESQLVIEWVCustomersREMOTECONNECTIONNorthwindSHARE;
ASSELECT*FROMCustomersWHEREcustomeridLIKE"ALFKI"
又如,VisualFoxPro中删除字符型字段的空格可使用ALLTR()函数,但远程视图的SELECT-SQL中不能用任何VisualFoxPro的函数,所以要实现上述功能,应如下使用SQLServer的函数:
CREATESQLVIEWVCustomersREMOTECONNECTIONNorthwindSHARE;
ASSELECTcustomerid,LTRIM(RTRIM(CompanyName))FROMCustomersWHEREcustomeridLIKE'ALFKI'
4.第三点中我们强调了远程视图构建时必须使用后端数据库认识的Select-SQL。
当远程视图被打开,成为VisualFoxPro的光标时,就可以对它使用VisualFoxPro的命令与函数。
CREATESQLVIEWVEmployees;
REMOTECONNECTIONNorthwindSHARE
ASSELECTEmployeeID,BirthdateFROMEmployees
WHEREBirthDate>?
dBirthdate1ANDBirthDate
dBirthdate2
dBirthdate1='19540101'
dBirthdate2='19601231'
USEVEmployees
BROWSE
*本例对日期型字段Birthdate使用了两个参数,并请注意日期型参数的传递。
CREATESQLVIEWVEmployees1;
REMOTECONNECTIONNorthwindSHARE;
ASSELECTEmployeeID,BirthDate,CountryFROMEmployees;
WHEREbirthDate>?
dBirthdateANDCountry=?
cCountry
dBirthdate='19601231'
cCountry='uk'
USEVEmployees1
BROWSE
*本例对两个字段设定了参数
只下载有用的字段
上文中我们使用SELECT*从远端一古脑儿把所有列都下载到客户机,这样做不好。
原因如下:
1.对远程数据操作时并不是所有的列(字段)都会被我们用到,特别是备注字段、大二进制字段。
2.在视图阶段就可以通过计算有关列得到更有用的信息,见下面的代码。
3.明确指定列信息有助于VisualFoxPro对远程数据表的版本控制。
如果使用SELECT*,那么只有在远程数据表增加字段时VisualFoxPro才知道,其他如减少、变更列的结构VisualFoxPro都不会知道。
例如:
远程表中有FirstName,LastName列,我们在制作报表时只需要全名就可以了,那么我们解可以将它们相加成为一个新的列。
CREATESQLVIEWVEmployees1;
REMOTECONNECTIONNorthwindSHARE;
ASSELECTEmployeeID,FirstName+''+LastNameASName,Title;
FROMEmployees
多表连接形成的远程视图
远程视图不仅支持远程一个表的操作,它还支持多表连接,如下:
CREATESQLVIEWVEmployeeTerritories;
REMOTECONNECTIONNorthwindSHARE;
ASSELECTTerritories.TerritoryID,Territories.TerritoryDescription,Employees.EmployeeID,;
Employees.LastName,Employees.FirstName;
FROMTerritoriesINNERJOIN;
EmployeeTerritoriesON;
Territories.TerritoryID=EmployeeTerritories.TerritoryIDINNERJOIN;
EmployeesONEmployeeTerritories.EmployeeID=Employees.EmployeeID
远程视图还支持自连接,如下:
CREATESQLVIEWVEmployeeReportTO;
REMOTECONNECTIONNorthwindSHARE;
ASSELECTEmployees.EmployeeIDas领导工号,;
Employees.FirstName+''+Employees.LastNameas领导,;
Employees_a.FirstName+''+Employees_a.LastNameas下属,;
Employees_a.ReportsToas上级领导工号;
FROMEmployeesEmployeesINNERJOIN;
EmployeesEmployees_aON;
Employees.EmployeeID=Employees_a.ReportsTo;
ORDERBYEmployees_a.ReportsTo
从上面的语句大家可以发现:
VisualFoxPro中的SQL与SQLServer中的SQL十分相似,这方便了学习,但千万别陷入了“温柔陷阱”!
用vfp与sqlserver构建Client/Server应用程序(远程视图)(3)
可更新视图(Updatebleviews)
上面我们讲解了“怎样通过远程视图从服务器中把数据读取过来”,接着我们要讲解怎样操作远程视图光标,当然我们不会在这里讨论一些VisualFoxPro数据集的普通操作,这里我们只讲解远程视图的数据更新。
当远程视图被打开,用户就可以使用VisualFoxPro的命令与函数作光标进行各种操作,例如查询、新添数据、删除记录、修改记录等,后三者都会使数据发生变动,远程视图有着自动分析各种变动并把变动的结果发送到后端数据库更新数据源的功能。
顺便提一下,VisualFoxPro在数据更新这方面的的能力是非常强大的——如果一个视图是由多个数据源表连接而成,VisualFoxPro能够自动分析客户端数据变动所对应的数据源信息,“分门别类”对远程数据数据进行的更新。
现在一些非常著名的数据引擎中都不具备这个功能,详细情况请看本站文集中的《VisualFoxPro漫谈》一文。
键值栏、可更新字段、SQL更新开关
我们可以通过“视图设计器”制作可更新的远程视图(当然可以用它设计上文提到的那些远程视图),如图7。
为了设定一个远程视图为可更新视图,在视图设计器中您必须多做三件事情(比不可更新的远程视图):
1.设定键值栏。
系统之所以能够知道你变动了视图中的那一笔记录并在数据源中作出相应的变动,就是依靠键值来判断的。
可以这样理解:
键值就是能够惟一标识表中数据记录的标记。
键值是不可以重复的。
设想一下在一个员工表中,您把性别设定为键值,并修改某一员工的姓名,然后发送更新,这会造成什么结果(事实上VisualFoxPro会报告键值不唯一的错误,我们假设VisualFoxPro不报错):
与该被修改姓名的员工具有相同性别的员工的名字都被修改了,很可笑吧!
一般VisualFoxPro会自动从SQLServer中把键值信息读到,并自动设定