我刚刚使用for更新光标遇到了ASE(版本15.7 ESD 15.2)的奇怪行为 最后我发现了根本原因,但是我想把它发布在这里,因为它可能很有用,也许有人已经面对它了。
我写了这个简单的"用于更新"光标:
DECLARE c_contactrule
CURSOR FOR
SELECT a.id
FROM FTContactRule a, Client b, ClientContact c
WHERE /* join conditions */
AND a.client_id IN ( bla bla bla )
AND a.message_subtype_id ( bla bla bla )
AND /* and so on */
for update of a.preferred_medium_id
go
(我总结了一下这篇文章的查询,以便更具可读性)
此后,当然,我读取光标值直到结束。
open c_contactrule
fetch c_contactrule into @rule_to_update
while @@sqlstatus = 0
begin
/* do something */
end
close c_contactrule
deallocate c_contactrule
go
我想你猜到某个地方update preferred_medium_id where current of
目前,这个查询以一种非常具体的方式崩溃:抛出的消息是" ASE终止了这个过程",实际上,他杀了我的会话!
调查,我发现不好的代码行是第一个fetch into
语句。
答案 0 :(得分:1)
如果ASE终止了会话,那么您在运行ASE时遇到了错误。唯一的补救措施是升级到包含修复程序的更新版本。检查TechSupport是否可以识别错误(错误日志中应该有堆栈跟踪)以及是否有可用的修复程序。
如果你以不同的方式重写你的查询,例如导致不同的查询计划,可能没有命中bug,但这不是保证(也不是一个非常令人安慰的解决方案)
答案 1 :(得分:0)
我终于找到导致此错误消息的原因,但我仍然认为这是一个错误,因为崩溃是对服务器的反应太难了。应该有一个更加用户友好的消息或解析错误,但不是一个无声的杀戮。
无论如何,我的测试表明问题是由于我更新了一个不在游标的select语句中的字段:
select a.id
....
for update of a.preferred_medium_id
我刚刚在选择列表中添加了字段,当然我在fetch中添加了一个变量,它运行正常。
select a.id, a.preferred_medium_id
....
for update of a.preferred_medium_id
然而,当你不需要对它做任何事情时,必须在变量中保存一个值有些奇怪。
此外,终止会话并不是服务器的良好响应。如果有一个语法规则,那么我们应该有一个解析错误说"你不能更新一个不在你的选择列表中的字段来取消更新游标"