您的位置:首页 > 数据库

如何将VFP本地表数据传送到SQL-Server后台进行更新

2006-05-30 16:57 701 查看
前言:
讲解涉及到VFPSQL-Server的并不多,MSDN中主要介绍的是VFP如何通过SPTSQL-Server进行通讯的常用几个函数,连接、断开、执行、设置环境等。

我在MSDN中找了很久,也许是她的内容太多了,我始终没有找到一个介绍如何将VFP本地表传递到SQL-Server进行存储的例子(所有涉及视图的例子除外)。

为什么不采用视图呢?可以说没有为什么,这也是我个人的喜好,我不喜欢后台用了SQL-Server后,前台还需要搞个什么视图,而为了这个视图还要创建一个数据库(DBC),那么前台还要来维护这个数据库。不知道是不是因为不了解数据库(DBC)所以不懂如何维护好她,反正我见过很多次就是因为DBC莫名其妙的问题导致程序无法正确的执行。。。

我喜欢前台干干净净的就一个EXE文件足以,而且这个文件放哪个目录都可以正常运行,程序设置性的数据可放置在注册表,或者放在INI配置文件。而INI配置文件又可放在Windows系统目录下,象System.ini、Win.ini那些一样。。。

好像有点跑题了,呵呵,下面言归正传了。。。

将本地表的数据传到服务器的方法很多种,当然我们得根据自己实际的需要进行。虽然DTS功能很强大,但未必能满足我们的要求。尤其是我们做的一个数据输入画面,或者一个小的数据更新执行时,好像用DTS有点小题大做吧?呵呵,我不知道高手们是不是用DTS都能搞定本文所涉及的中心思想,反正我在SQL-Server2000的帮助中看了一晚上的DTS方面的文字,还是有点晕~~

下面我们来看一个例子。

实例介绍:
SQL-Server数据库上有一个表,因为为了测试,我给她取名test,她有3个字段,分别是自动增长型的ID(int)字段(默认0),一个字符的字段TEST(varchar),一个逻辑字段LL(bit)(默认0)。

注意:从这个实例中大家是不是想想为什么用这个例子来说明。

该表的结构很简单,只是为了说明问题,TEST字段是一个可以随便修改的字段,类似一些描述、名称、备注、标题之类的性质,她的值的内容并不是很重要。而字段LL是一个标记性字段,因为她是逻辑型嘛,她起的作用是这样的:只有当LL=0的时候,才可以修改TEST字段的内容,而且修改后,要置LL=1,之后这条记录就不能再修改了。指字段TEST的值就不再修改了。好像被LL字段确认过了,不能再确认了。

以下是在SQL-Server的查询分析器中运行的两段代码:

代码1
Declare @bitError bit
Set @bitError=0
Begin Transaction
Update test
Set TEST = GetDate(),
LL = 1
Where ID = 13 and LL=0
If @@Error<>0 or @@RowCount<>1 Set @bitError=1
--
If @bitError=0
Commit
Else
Rollback
--
Select Case @bitError
When 0 Then '成功!'
When 1 Then '失败!'
End
as 结果
代码2
Begin Transaction
Update test
Set TEST = GetDate(),
LL = 1
Where ID = 13 and LL=0
If @@Error<>0 or @@RowCount<>1 goto ErrorHandle
Commit
Select '成功' as 结果
return

ErrorHandle:
Rollback
Select '失败' as 结果
return
代码说明:
以上代码1代码2的效果是一样的,都是为了更新表test中字段ID=13,并且LL=0的记录,使字段TEST等于当前的日期,字段LL的值由逻辑假到逻辑真。

当执行完UPDATE命令后,会改变2个系统变量(暂不管还改变了其他什么系统变量)@@Error和@@RowCount,如果命令执行有错,@@Error就是记录错误的代码,没有错则@@Error=0。按正确更新时UPDATE命令应该只更新一个记录,但是当更新时,表中的ID=13的记录上LL已经等于1时,再次执行UPDATE势必就是违反了先前说过的意思,就是不能再确认了,因此在WHERE条件的LL=0中就不会满足,导致一个记录都没更新到,从而改变系统变量 @@RowCount=0,这个结果就是错误的,正确更新应该是@@RowCount=1时才对!
代码1代码2的区别在只更新一个记录时体现的不是很明显,如果多个记录同时更新时,主要表现
update …
if … set …

update …
if … goto …
以上分别两行代码其实是应该由客户端循环处理产生的N个组合。代码量上应该差不多,可当中间有更新时错误时,代码1的方案会继续更新,因为事物提交/回滚在最后才执行的。而代码2的方案会在一旦遇到更新错误时就直接到最后进行回滚了。

以上的代码都是后台直接运行的,我们可以在VFP中将他们放在一个变量中,然后将这个变量传递到后台执行,大家可以试下2组代码分别有什么不同。如果是代码1,当代码中含有错误的命令时,比如将TEST表名打错,使得到一个不存在的表,那么运行时是会产生错误的。可代码1不会返回错误,而代码2则会返回后台产生的错误!

我试过是因为代码1中有Set @bitError=0 这样的赋值语句。至于原因,我也不得而知了。
所以代码1的方案不可取,除非她在后台的存储过程中呆着。
可是测试代码2时,按理论上应该返回一个光标文件,字段为“结果”存着“成功”还是“失败”的记录,后台运行时会按自己的想法去执行,可在VFP中,什么都没有,有时还会出现错误,叫“不能从服务器返回记录集”!

为了实现上述代码所达到的目的,通过改写代码,在VFP中按以下代码3的编写规则书写即可得到比较理想的答案(至少我现在觉得比较好)。

代码3
IF RunSQL("Begin transaction")
RunSQL("Update test set test = GetDate(),ll=1 where ID = 13 and ll=0")
RunSQL("Select @@Error as nError,@@RowCount as nRowCount")
IF nError#0 OR nRowCount#1
*-- 更新失败
RunSQL("Rollback")
MESSAGEBOX("更新错误,或数据没有更新到,总之此次更新失败!",16,"更新")
RETURN
ELSE
*-- 更新成功
RunSQL("Commit")
MESSAGEBOX("成功更新!",64,"更新")
ENDIF
ENDIF
代码说明:
代码3中的RunSQL() 是自定义函数,主要是调用 =sqlexec()
代码的第3行至所以能这么写,是因为@@Error和@@RowCount是系统变量,如果是自己定义的又不是全局变量的则不能这么使用,会提示找不到变量的错误!

参考代码:
调用SQL上的一个DTS包进行DOS方式下执行:
EXEC xp_cmdshell 'DTSRun /S "(local)" /U "sa" /N "DTS 转换测试" /G "{AA52E887-9372-4036-A501-1E50C559D05A}"'
(下划线部分是DOS下可以运行的命令)

同时向服务器添加多个记录时:
*-- 开始一个事务
IF !RunSQL("Begin Transaction")
RETURN .F.
ENDIF

SELECT temp_SelectPers
ShowProcessBar(Submiting_loc,RECCOUNT()+1)
SCAN
oProcessbar.showbar(RECNO())
lcPerID = ALLTRIM(STR(ID))
lcSQL = "Insert into l_jobs (。。。) values (。。。)"
IF RunSQL(lcSQL) && 执行插入命令
IF RunSQL("Select @@Error as nError,@@RowCount as nRowCount") && 返回执行的状态
IF nError#0 OR nRowCount#1
*-- 更新失败
RunSQL("RollBack") && 进行回滚
MESSAGEBOX(Fail_loc,16,stop_loc)
showbar(RECCOUNT("temp_SelectPers")+1)
RETURN .F.
ENDIF
ENDIF
ELSE
RunSQL("RollBack")
showbar(RECCOUNT("temp_SelectPers")+1)
RETURN .F.
ENDIF
ENDSCAN

showbar(RECCOUNT("temp_SelectPers")+1)

IF RunSQL("Commit")
MESSAGEBOX(DataSaved_loc,64,info_loc)
ENDIF
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐