很多人认为有了远程视图这样直观、简单的工具,为什么还需要 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=sql server;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 customersswheres customerid=/'test/')"
csql=csql+" delete from customersswheres 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 customersswheres customerid=/'"+custid+"/')"
csql=csql+" delete from customers swherescustomerid=/'"+custid+"/'"
csql=csql+" else insert customers(customerid,companyname) values(/'"+custid+"/',/' 这是一个测试! /')"
?sqlexec(con,csql)
2、spt 标准变量传递法
custid=/'test/'
csql="if exists(select * from customersswherescustomerid=?custid)"
csql=csql+" delete from customersswherescustomerid=?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 customersswherescustomerid=/'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 customersswheres 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 中也可以进行同样的处理。
本文开始已提到 vfp 在这方面的内容很广泛,寥寥千言当然不能尽言,有兴趣的朋友可以去访问www.boeworks.com,以便查阅更多的内容。ok,希望有机会与大家一起讨论这方面的问题。
新闻热点
疑难解答