关于VFP和SQL Server的
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于VFP和SQL Server的相关的知识,希望对你有一定的参考价值。
请问一下在VFP中,使用sql server数据库,SQL语句中的select语句应该怎样执行。有没有哪个函数可以执行select语句并返回结果的?
熟悉 VFP的朋友都知道,在 VFP 里我们可以使用远程视图 (Remote View) 和 SPT(SQL Pass Through) 技术控制远程异构数据库。这些技术其实是 VFP 对 ODBC 的 API 的封装,所以对于用户来说访问远程数据库就像操作传统的DBF一样简单。关于这两种技术的使用,完全可以洋洋洒洒地写下一本书,鉴于本文主题及篇幅,这里仅枚举 SPT 技术访问远程数据的应用。很多人认为有了远程视图这样直观、简单的工具,为什么还需要 SPT 呢?确实 SPT 较远程视图难以掌握,但细细体会你会发现:远程视图其实是对 SPT 的可视化工具!SPT 较远程视图更具威力,远程视图提供的功能只是 SPT 的一个子集。其优势和劣势主要体现在以下几个方面:
l、SPT 的优势
1) 一次得到多个Cursor;
2) 执行除 Select 以外的其他 SQL 语句,如 Insert、Update、Delete等;
3) 执行远程数据库的存储过程 ;
4) 执行远程数据库的特殊函数、命令等 ;
5) 事务管理 。
2、SPT 的劣势
1) 没有图形用户界面;
2) 必须人工维护连接;
3) 得到的Cursor默认是“可读写”Cursor,要使它成为“可更新”Cursor必须经过设置才行。
下面就顺着我们对 SPT 的认识,来浏览一下这个伟大的工具吧!(注意:本文所有例程均使用 SQL Server的NorthWind 数据库演示)。
管理连接
l、建立连接
注意:本文所有示例的代码若用到连接的,默认采用“建立连接”代码中产生的连接句柄 “CON”。
WAIT ' 连接到 SQL Server 上去 ' NOWAIT NOCLEAR WINDOW
SQLSETPROP(0,"DispLogin" ,3) &&&& 设置环境为“从不显示 ODBC 登录对话框”。
CON=SQLSTRINGCONNECT("driver=SQLServer;Server=BOE;Uid=sa;pwd=;database=northwind")
*假定 SQL Server 服务器名为 BOE, 用户 ID 是sa, 口令是空串
*如果你的 SQL Server 的服务器名, 用户 ID, 口令与上不同,请修改以上代码中的相关部分以符合你系统中的设置
WAIT clear
IF con<=0
MESSAGEBOX(' 连接失败 ',64,' 连接到 SQL Server 上去 ')
ELSE
MESSAGEBOX(' 连接成功 ',64,' 连接到 SQL Server 上去 ')
ENDIF
2、断开连接
SQLDISCONNECT(CON)
一次得到多个Cursor
我们可以用一次 SPT 传回多个Cursor,如下:
cSQL="SELECT * FROM EMPLOYEES"+CHR(10)+"SELECT * FROM CUSTOMERS"+CHR(10)+"SELECT * FROM PRODUCTS"
?SQLEXEC(con,cSQL,"TEMP")
SQLEXEC( ) 的返回值表示Cursor的数量,这里返回 3 。这三个Cursor分别以 TEMP、TEMP1和TEMP2 命名。
执行其他 SQL 语句
下面我们尝试执行SQL Server以外的SQL语句:
cSQL="IF EXISTS(SELECT * FROM CUSTOMERS where CUSTOMERID='TEST')"
cSQL=cSQL+" DELETE FROM CUSTOMERS where CUSTOMERID='TEST'"
cSQL=cSQL+" ELSE INSERT CUSTOMERS(CUSTOMERID,COMPANYNAME) VALUES('TEST',' 这是一个测试! ')"
IF SQLEXEC(CON,cSQL)<=0
MESSAGEBOX(' 执行失败 ',64,' 发送语句到 SQL Server 上去 ')
ELSE
MESSAGEBOX(' 执行成功 ',64,' 发送语句到 SQL Server 上去 ')
ENDIF
行文至此,也许有朋友会问:如果 SQL 语句中 CUSTOMERID 是一个变量怎么办呢?其实 我们可以通过两个常用的解决方案来解决:
1、拼接字符串
CUSTID='TEST'
cSQL="IF EXISTS(SELECT * FROM CUSTOMERS where CUSTOMERID='"+CUSTID+"')"
cSQL=cSQL+" DELETE FROM CUSTOMERS where CUSTOMERID='"+CUSTID+"'"
cSQL=cSQL+" ELSE INSERT CUSTOMERS(CUSTOMERID,COMPANYNAME) VALUES('"+CUSTID+"',' 这是一个测试! ')"
?SQLEXEC(CON,cSQL)
2、SPT 标准变量传递法
CUSTID='TEST'
cSQL="IF EXISTS(SELECT * FROM CUSTOMERS where CUSTOMERID=?CUSTID)"
cSQL=cSQL+" DELETE FROM CUSTOMERS where CUSTOMERID=?CUSTID"
cSQL=cSQL+" ELSE INSERT CUSTOMERS(CUSTOMERID,COMPANYNAME) VALUES(?CUSTID,' 这是一个测试! ')"
?SQLEXEC(CON,cSQL)
特殊函数和命令
如果在 SQL Server 中你有足够的权限,通过 SPT 使用远程数据库的特殊函数和命令,你可以完全控制 SQL Server ,这里我们就演示“怎样取得数据库服务器的时间”:
?SQLEXEC(con,"select getdate() as serverdatetime","temp1")
?temp1.serverdatetime
USE IN ("temp1")
事务管理
在一些复杂的应用中,往往会有一项操作影响几个表的情况。就客户端来说,发送到远程数据库的数据变动可能来源很多:表缓冲的多行记录的变动,行缓冲的单行记录变化,以及前文我们演示的直接用 SQL 语句传递的数据维护,林林总总……怎样把这些更新行为控制在一个事务中呢!要么一起成功,要么一起回滚。
cSQL="DELETE FROM CUSTOMERS where CUSTOMERID='BLAUS'"+CHR(10)
cSQL=cSQL+"INSERT CUSTOMERS(CUSTOMERID,COMPANYNAME) VALUES('TEST1',' 这是一个测试! ')"
SQLSETPROP(CON,"Transactions" ,2)&&&& 开始一个事务
IRETURN=SQLEXEC(CON,cSQL)
IF IRETURN=1
SQLCOMMIT(CON)&&&& 事务交付
ELSE
SQLROLLBACK(CON)&&&& 事务回滚
ENDIF
SQLSETPROP(CON,"Transactions" ,1)&&&& 重新回到自动事务处理状态
&&&&就本例而言,“DELETE FROM CUSTOMERS where CUSTOMERID='BLAUS'”总是不能执行的,SQL Server会返回出错揭示:
&&&&DELETE statement conflicted with COLUMN REFERENCE constraint 'FK_Orders_Customers'.
&&&&The conflict occurred in database 'Northwind', table 'Orders', column 'CustomerID'.
&&&&所以这笔事务总是被回滚的!!
从例程中可以看到,我们开启的事务其实是针对“连接”的,也就是说通过该“连接”的所有数据更新都包含于事务中,直到事务被回滚或交付。
SQLSETPROP(CON,"Transactions" ,2 ), 其实是开启了人工事务处理,也就是说必须由用户明确地给出交付或者回滚指令,事务才会结束。所以笔者以为:完成一笔事务以后,应执行 SQLSETPROP(CON,"Transactions" ,1 ) 将“连接”的事务模式设为默认的“自动”,这样可以防止用户陷入未知的事务中去。
SPT的基本操作还不止这些,以后我们还会为读者朋友介绍其他一些基本操作。如果朋友们能掌握这些基本操作,就能编写不错的 C/S 程序了。虽然本文是用 SQL Server 作为远程数据库,但是如果你使用 DB2和Oracle等,在 VFP 中也可以进行同样的处理。 参考技术A 1. EXISTS谓词
存在量词$
带有EXISTS谓词的子查询不返回任何数据,只产生逻辑真值“true”或逻辑假值“false”。
若内层查询结果非空,则外层的WHERE子句返回真值
若内层查询结果为空,则外层的WHERE子句返回假值
由EXISTS引出的子查询,其目标列表达式通常都用* ,因为带EXISTS的子查询只返回真值或假值,给出列名无实际意义
2. NOT EXISTS谓词
若内层查询结果非空,则外层的WHERE子句返回假值
若内层查询结果为空,则外层的WHERE子句返回真值
in比较简单我就不说了……本回答被提问者采纳
VFP执行 SQL Server 储存过程示例
PUBLIC errval
PUBLIC errmsg
PUBLIC handle
errval=0
errmsg=‘ ‘
*Sql Server 连接参数
sourcename= ‘test‘
user= ‘sa‘
passwd=‘‘
******** 连接
* 为连接打开错误显示
=SQLSetProp(0,"DispWarning",.t.)
handle=SQLConnect(sourcename,user,passwd)
IF handle > 0
WAIT WINDOW ‘连接成功‘ NOWAIT
ENDIF
******** 设置一些默认值
=SQLSetProp(handle,‘Asynchronous‘,.f.)
=SQLSetProp(handle,‘BatchMode‘,.t.)
=SQLSetProp(handle,‘ConnectTimeOut‘,0)
=SQLSetProp(handle,‘Transactions‘,1)
err=SQLExec(handle,‘use pubs‘)
DO errhand WITH err,‘USE PUBS‘
********** 该程序演示如何实现 SQL 的 SQLExec() 函数
sqlcomm= "execute showsales ‘7066‘"
err=SQLExec(handle,sqlcomm)
DO errhand WITH err,"SQLExec(handle,"+sqlcomm+")"
IF err > 0
BROWSE
ENDIF
********** 断开
err=SQLDisconnect(handle)
DO errhand WITH err,"SQLDisconnect()"
CLOSE ALL
********** 错误处理程序
PROCEDURE errhand
PARAMETERS err,command
IF err > 0
WAIT WINDOW ALLTRIM(UPPER(command))+"完全成功" NOWAIT
ELSE
WAIT WINDOW UPPER(command)+"没有完全成功"
ENDIF
RETURN
注意程序返回两个 stor_id 为 7066 的记录.
以上是关于关于VFP和SQL Server的的主要内容,如果未能解决你的问题,请参考以下文章