相关链接:FAQ:
TS-SQL操作及其效率的分析
问题报错操作代码:
ret:=update sqltable 'FutureArchive' of 'DBName' set ['IsValid']=0
where ['TSID']=5881 end ;
if ret=0 then return sqlerrormsg()
else return ret;
经常操作不成功,报如下错误:
问题分析:
从该段代码中可以看出,sqltable后面是表名,相当于select *取整个表的数据,处理整张表的游标集,若表格很大的话,效率会很低。
原因是,本条语句是将整个表格中每一条记录从数据库中复制到客户机,然后用TS-SQL对整表的数据进行where条件定位再做update,完全没有用到数据库的任何SQL。
造成以下几个问题:
1、由于TSL-SQL基于DBMS客户机处理整个表,导致整个过程游标量巨大,内存消耗巨大、处理速度极慢。(此时,sqltable会比hugesqltable更大)
2、造成冲突,原因是操作时其他操作导致游标组变更,变更时导致冲突。
当利用巨大的游标集在做TS-SQL更新操作时,后台有另外的程序对该表进行了update/delete等操作,在遍历时有可能将需要更新的游标已经做了更改,导致该游标实际已消失,这种情况下,对现有的游标组会出问题,导致报错。
所以,会有时操作成功,而有时操作报冲突错误。
报冲突错误原因通俗点可以理解为,由于数据集过大,处理效率慢,导致执行时间长,当期间后台有人修改了表的数据时,那么就会报这个冲突错误。
解决办法一:用SQL缩小更新范围,优化效率,减少游标占用时间,降低出错率
例如:将where子语句在SQL层操作,减少游标量
ret:=update sqltable 'select * from FutureArchive where tsid=5881'
of 'DBName'
set ['IsValid']=0 end ;
if ret=0 then return sqlerrormsg()
else return ret;
解决办法二:用EXECSQL交互
EXECSQL的劣势:由于SQL对字符串的大小以及BLOB等类型无法支撑,TS-SQL是一种便捷的方案。
EXECSQL的优势:
完全SQL操作,使用数据库的本身,执行效率高。
通过参数支持模式,可以将复杂类型数据传递给SQL。
例如,上面的案例代码可以用以下代码来实现:
sql:="update FutureArchive set IsValid=0 where tsid=5881";
ret:=execsql('DBName',sql,data);
if ret=0 then return sqlerrormsg()
else return ret;
与数据库交互方式的建议
1、做select/update/delete操作时,可尽量用EXECSQL方式交互。
2、SQL操作比TS-SQL操作效率高,在使用TS-SQL操作数据库时,尽量将where子语句放到SQL中完成,达到减少TS-SQL操作,提高执行效率,降低冲突事件发生的概率的目的。