在VFP8.0中使用SPT技术对SQL数据库表进行读写编程操作时遇到的的问题如何解决?

时间:2022-10-27 21:45:19
在VFP8.0中使用SPT技术对SQL数据库表进行读写操作,所编程序为:

cnn= sqlstringconnect ('dsn=myconn')
if cnn<= 0 
messagebox("连接错误",16,"连接到SQL Server")
else
sqlexec(cnn, "select * from rsda ","mycorsor")  
sele mycorsor 
cursorsetprop("tables","rsda"," mycorsor ") &&设置临时表的更新目标表 
cursorsetprop("keyfieldlist",'id'," mycorsor ") &&设置临时表的关键字 
cursorsetprop("updatablefieldlist","id,fzdw,rghsj,ghzrsj,hyzhm","mycorsor")&&设置临时表的更新字段
cursorsetprop("updatenamelist","id rsda.id,hyzhm rsda.hyzhm,rghsj rsda.rghsj,ghzrsj rsda.ghzrsj,fzdw rsda.fzdw"," mycorsor ") &&用mycorsor中的相应字段更新rsda表 
cursorsetprop("sendupdates",.t.," mycorsor ")&&设置为可更新 
cursorsetprop("wheretype",2) 
cursorsetprop("buffering",5)&&设置表缓冲 
endif 

在实际运行程序过程中,发生以下问题:
1、使用sqlexec(cnn, "select * from rsda ","mycorsor")函数建立和SQL数据库表rsda的连接时,该句仅执行一次不能和SQL数据库表建立连接,需要再执行一次才能建立连接并产生临时表mycorsor。在编程时需要将命令重复一次,编成:
sqlexec(cnn, "select * from rsda ","mycorsor")  
WAIT "" timeout 0.1
sqlexec(cnn, "select * from rsda ","mycorsor") 
只有这样才能和SQL数据库表建立连接并产生临时表。
2、在执行完所编程序后,使用可更新临时表mycorsor进行数据修改(当光标离开修改行时)或增添记录时,不能进行操作,出现出错提示“未指定要更新的表,请使用临时表的Tables属性。”
3、在所编程序中加入设置表缓冲命令cursorsetprop("buffering",5)后,能对可更新临时表mycorsor进行数据修改,修改后再执行sqlcommit(cnn)命令将修改结果写到后端SQL数据库表rsda中时,又出现出错提示“执行SQLEXEC( ) 序列时进行了无效的调用”,不能进行操作。
4、在所编程序中加入设置表缓冲命令cursorsetprop("buffering",5)后,对可更新临时表mycorsor进行数据修改,然后再执行TABLEUPDATE(0)命令,发现后端SQL数据库远程表rsda数据并没有更新。
敬请电脑专家分析,编程中有哪些错误,所提问题产生原因、怎样解决?如何正确地使用SPT技术对SQL数据库表进行读写编程操作?敬请指导,不胜感激!

9 个解决方案

#1


帮顶~~~

#2


1、出现这问题很奇怪,第一条sqlexec失败的错误原因要找出来 aerror(..)
2、既然设为表缓冲,行更改不会提交SQL命令。你cursorsetprop时,要检测是否成功
3、提交表缓冲,是用tableupdate, 如果你的事务状态为自动autocommit,就不用sqlcommit,除非你手动启动一个事务
4、

spt提交其实很简单,
设定cursorsetprop只是告诉vfp,你的临时表和服务端表的对应关系。此时vfp不会发送命令到服务端来验证你的设定。

当buffer设为行缓冲(3),离开行时或tableupdate(0,..),VFP根据GETFLDSTATE获知你是否增加/修改/删除行,若是,根据以上cursorsetprop设定的对应关系,构造SQL语句(INSERT,UPDATE,DELETE)发送到服务端

当buffer设为表缓冲(5),执行tableupdate(0,..), 提交该行,tableupdate(1,..), 提交整表,提交整表是循环提交行。

你大概知道问题出在哪里了。如果有问题,可以tracet一下odbc, 看看问题出在哪里。

#3


1、问题比较怪,不好说,可能与上下文代码有关?也可能其他。
2-4、你要理解表缓冲和行缓冲的不同,这个可以仔细参考VFP自带帮助中的相关代码。
     如果缓冲用不好,可以不用,就直接sqlexec(cnn, "Update 或 Insert 语句")来更新 SQL Server,即不设置表或行缓冲。
     如果数据量不大的话,也可以用远程视图,这个与临时表更新远程表差不多,这个请参考:

http://topic.csdn.net/u/20081023/20/357912ac-3a16-42f9-8fd0-030c2a148ec0.html?seed=484906614

#4


  CURSORSETPROP('buffering',5,'zqq')
 N2 = CURSORSETPROP('TABLES','200312')
 N3 = CURSORSETPROP('KEYFIELDLIST','BH')
 N4 = CURSORSETPROP('UPDATABLEFIELDLIST','NY,XM,DW,DWDM')
 N6 =  ;
      CURSORSETPROP('UPDATenamelist','bh 200312.bh,ny 200312.ny,xm 200312.xm,dw 200312.dw,DWdm 200312.DWDM','zqq')

应该是庑设置buffering吧,SQLSERVER表是否有主键

#5


trainee、十豆三专家:
   谢谢指导!
   第一个问题可能是与我的计算机上SQL数据库设置有关,使用sqlexec(cnn, "select * from rsda ","mycorsor")函数建立和SQL数据库表rsda的连接必须执行二次命令才能连接,但我在另一台计算机调试不存在这个问题。不知道是什么原因。
   第二个问题得不到解决。我是执行了一系列CURSORSETPROP命令(指定临时表和服务端表的对应关系),并将临时表buffer设为表缓冲(5)后,打开临时表,对临时表进行多行修改,然后执行tableupdate(1,.t.,"mycorsor"),发现该函数返回值是.F., 对临时表的修改不能发送到服务器端,服务器所对应的表不能被修改。
   敬请专家指导,如何解决这一问题?不胜感激!
   (远程视图是可以解决这一问题的,但由于数据量大,速度很慢,我想通过使用SPT技术来提高运行速度。)

#6


能否用AERROR捕获到错误

#7


你要是数据量大,也不建议用表缓冲,也会速度慢,改用行缓冲吧。

#8


不知道你参考过这个例子吗?

临时表更新SQL表的例子
*------------------------

SQL服务器名:MyServer
SQL用户名:sa
SQL用户名:空

SQL中的表名:Kq_Yg
Kq_Yg表的字段:     Id  Int  4
Name  Char  10
Department  Char  20

以下是FORM信息:

Form上有5个按钮,一个Grid,分别为:

1 、增加(AddCmd),Click事件:
Select  Temp1
Append  Blank
Thisform. SaveCmd. Enabled= .T.
Thisform. Grid1. Refresh
Thisform. Grid1. ReadOnly= .F.
Thisform. Grid1. SetFocus

2 、修改(EditCmd),Click事件:
Thisform. SaveCmd. Enabled= .T.
Thisform. Grid1. ReadOnly= .F.
Thisform. Grid1. SetFocus

3 、删除(DelCmd),Click事件:
Delete
Thisform. Grid1. Refresh
Thisform. SaveCmd. Enabled= .T.

4 、保存(SaveCmd),此按钮的Enabled值为 .F. ,Click事件:
Select  Temp1
lSuccess= CursorSetProp( "sendupdates", .T., "Temp1") &&设置为可更新
m.lSuccess= Tableupdate( .T., .F.&&successful update
If  m.lSuccess
     Messagebox( "保存成功!", 64, "信息提示")
     Thisform. SaveCmd. Enabled= .F.
     Thisform. Grid1. ReadOnly= .T.
Else
     Messagebox( "保存失败!", 16, "信息提示")
     Thisform. SaveCmd. Enabled= .T.
     Thisform. Grid1. ReadOnly= .F.
     Tablerevert( .T.)
Endif

5 、退出(ExitCmd),Click事件:
SQLDisconnect( 0&&终止所有活动的连接。
Close  Databases
Thisform. Release

6 、Grid的ReadOnly值为 .T.

7 、Form的Init事件:
Close  Databases
Set  Safety  Off
Public  nhandle
nhandle= Sqlstringconnect( "driver=SQL Server;server=MyServer;uid=sa;pwd=;database=MyServer"&&无需配ODBC
If  nhandle<= 0
     Messagebox( "连接SQL Server 失败!!!", 16'错误信息')
     Cancel
Else
     Thisform. Grid1. RecordSource= Null
     Ac= SQLExec( nhandle, "Select * From Kq_Yg", "Temp1")
     If  Ac< 0
         Messagebox( "读取数据错误!", 16'错误信息')
         Cancel
     Endif
     Select  Temp1
     Thisform. Grid1. RecordSource= 'Temp1'
     Thisform. Grid1. Refresh
     Set  Multilocks  On
     CursorSetProp( "tables", "Kq_Yg", "Temp1")   &&设置临时表的更新目标表
     CursorSetProp( "keyfieldlist", "ID", "Temp1")   &&设置临时表的关键字
     CursorSetProp( "UpdateType", 1, "Temp1")   &&设置用新数据更新旧数据
     CursorSetProp( "updatablefieldlist", "ID,Name,Department", "Temp1") &&设置临时表的更新字段
     CursorSetProp( "updatenamelist", "ID Kq_Yg.ID ,Name Kq_Yg.Name,Department Kq_Yg.Department", "Temp1")   &&&用Temp1中的相应字段更新Kq_Yg表
     CursorSetProp( "wheretype", 2)
     CursorSetProp( "buffering", 5) &&设置表缓冲
Endif

#9


或者干脆不用缓冲。

#1


帮顶~~~

#2


1、出现这问题很奇怪,第一条sqlexec失败的错误原因要找出来 aerror(..)
2、既然设为表缓冲,行更改不会提交SQL命令。你cursorsetprop时,要检测是否成功
3、提交表缓冲,是用tableupdate, 如果你的事务状态为自动autocommit,就不用sqlcommit,除非你手动启动一个事务
4、

spt提交其实很简单,
设定cursorsetprop只是告诉vfp,你的临时表和服务端表的对应关系。此时vfp不会发送命令到服务端来验证你的设定。

当buffer设为行缓冲(3),离开行时或tableupdate(0,..),VFP根据GETFLDSTATE获知你是否增加/修改/删除行,若是,根据以上cursorsetprop设定的对应关系,构造SQL语句(INSERT,UPDATE,DELETE)发送到服务端

当buffer设为表缓冲(5),执行tableupdate(0,..), 提交该行,tableupdate(1,..), 提交整表,提交整表是循环提交行。

你大概知道问题出在哪里了。如果有问题,可以tracet一下odbc, 看看问题出在哪里。

#3


1、问题比较怪,不好说,可能与上下文代码有关?也可能其他。
2-4、你要理解表缓冲和行缓冲的不同,这个可以仔细参考VFP自带帮助中的相关代码。
     如果缓冲用不好,可以不用,就直接sqlexec(cnn, "Update 或 Insert 语句")来更新 SQL Server,即不设置表或行缓冲。
     如果数据量不大的话,也可以用远程视图,这个与临时表更新远程表差不多,这个请参考:

http://topic.csdn.net/u/20081023/20/357912ac-3a16-42f9-8fd0-030c2a148ec0.html?seed=484906614

#4


  CURSORSETPROP('buffering',5,'zqq')
 N2 = CURSORSETPROP('TABLES','200312')
 N3 = CURSORSETPROP('KEYFIELDLIST','BH')
 N4 = CURSORSETPROP('UPDATABLEFIELDLIST','NY,XM,DW,DWDM')
 N6 =  ;
      CURSORSETPROP('UPDATenamelist','bh 200312.bh,ny 200312.ny,xm 200312.xm,dw 200312.dw,DWdm 200312.DWDM','zqq')

应该是庑设置buffering吧,SQLSERVER表是否有主键

#5


trainee、十豆三专家:
   谢谢指导!
   第一个问题可能是与我的计算机上SQL数据库设置有关,使用sqlexec(cnn, "select * from rsda ","mycorsor")函数建立和SQL数据库表rsda的连接必须执行二次命令才能连接,但我在另一台计算机调试不存在这个问题。不知道是什么原因。
   第二个问题得不到解决。我是执行了一系列CURSORSETPROP命令(指定临时表和服务端表的对应关系),并将临时表buffer设为表缓冲(5)后,打开临时表,对临时表进行多行修改,然后执行tableupdate(1,.t.,"mycorsor"),发现该函数返回值是.F., 对临时表的修改不能发送到服务器端,服务器所对应的表不能被修改。
   敬请专家指导,如何解决这一问题?不胜感激!
   (远程视图是可以解决这一问题的,但由于数据量大,速度很慢,我想通过使用SPT技术来提高运行速度。)

#6


能否用AERROR捕获到错误

#7


你要是数据量大,也不建议用表缓冲,也会速度慢,改用行缓冲吧。

#8


不知道你参考过这个例子吗?

临时表更新SQL表的例子
*------------------------

SQL服务器名:MyServer
SQL用户名:sa
SQL用户名:空

SQL中的表名:Kq_Yg
Kq_Yg表的字段:     Id  Int  4
Name  Char  10
Department  Char  20

以下是FORM信息:

Form上有5个按钮,一个Grid,分别为:

1 、增加(AddCmd),Click事件:
Select  Temp1
Append  Blank
Thisform. SaveCmd. Enabled= .T.
Thisform. Grid1. Refresh
Thisform. Grid1. ReadOnly= .F.
Thisform. Grid1. SetFocus

2 、修改(EditCmd),Click事件:
Thisform. SaveCmd. Enabled= .T.
Thisform. Grid1. ReadOnly= .F.
Thisform. Grid1. SetFocus

3 、删除(DelCmd),Click事件:
Delete
Thisform. Grid1. Refresh
Thisform. SaveCmd. Enabled= .T.

4 、保存(SaveCmd),此按钮的Enabled值为 .F. ,Click事件:
Select  Temp1
lSuccess= CursorSetProp( "sendupdates", .T., "Temp1") &&设置为可更新
m.lSuccess= Tableupdate( .T., .F.&&successful update
If  m.lSuccess
     Messagebox( "保存成功!", 64, "信息提示")
     Thisform. SaveCmd. Enabled= .F.
     Thisform. Grid1. ReadOnly= .T.
Else
     Messagebox( "保存失败!", 16, "信息提示")
     Thisform. SaveCmd. Enabled= .T.
     Thisform. Grid1. ReadOnly= .F.
     Tablerevert( .T.)
Endif

5 、退出(ExitCmd),Click事件:
SQLDisconnect( 0&&终止所有活动的连接。
Close  Databases
Thisform. Release

6 、Grid的ReadOnly值为 .T.

7 、Form的Init事件:
Close  Databases
Set  Safety  Off
Public  nhandle
nhandle= Sqlstringconnect( "driver=SQL Server;server=MyServer;uid=sa;pwd=;database=MyServer"&&无需配ODBC
If  nhandle<= 0
     Messagebox( "连接SQL Server 失败!!!", 16'错误信息')
     Cancel
Else
     Thisform. Grid1. RecordSource= Null
     Ac= SQLExec( nhandle, "Select * From Kq_Yg", "Temp1")
     If  Ac< 0
         Messagebox( "读取数据错误!", 16'错误信息')
         Cancel
     Endif
     Select  Temp1
     Thisform. Grid1. RecordSource= 'Temp1'
     Thisform. Grid1. Refresh
     Set  Multilocks  On
     CursorSetProp( "tables", "Kq_Yg", "Temp1")   &&设置临时表的更新目标表
     CursorSetProp( "keyfieldlist", "ID", "Temp1")   &&设置临时表的关键字
     CursorSetProp( "UpdateType", 1, "Temp1")   &&设置用新数据更新旧数据
     CursorSetProp( "updatablefieldlist", "ID,Name,Department", "Temp1") &&设置临时表的更新字段
     CursorSetProp( "updatenamelist", "ID Kq_Yg.ID ,Name Kq_Yg.Name,Department Kq_Yg.Department", "Temp1")   &&&用Temp1中的相应字段更新Kq_Yg表
     CursorSetProp( "wheretype", 2)
     CursorSetProp( "buffering", 5) &&设置表缓冲
Endif

#9


或者干脆不用缓冲。