我正在尝试在Solaris上运行的sybase ASE 15.0.3系统的触发器中使用游标。这样做的目的是我想知道表的哪一列正在更新。然后,我将此信息保存在管理表中以供进一步查找。
create trigger test_trigger on my_table for update as
set nocount on
/* declare cursor */
declare @colname varchar(64)
declare column_name cursor for
select syscolumns.name from syscolumns join sysobjects on (sysobjects.id = syscolumns.id) where sysobjects.name = 'my_table'
/* open the cursor */
open column_name
/* fetch the first row */
fetch column_name into @colname
/* now loop, processing all the rows
** @@sqlstatus = 0 means successful fetch
** @@sqlstatus = 1 means error on previous fetch
** @@sqlstatus = 2 means end of result set reached
*/
while (@@sqlstatus != 2)
begin
/* check for errors */
if (@@sqlstatus = 1)
begin
print "Error in column_names cursor"
return
end
/* now do the insert if colum was updaed */
if update(@colname)
begin
insert into my_save_table (login,tablename,field,action,pstamp)
select suser_name(),'my_table',@colname,'U',getdate() from inserted
end
/* fetch the next row */
fetch column_name into @colname
end
/* close the cursor and return */
close column_name
go
不幸的是,当尝试在isql中运行它时,我收到以下错误:
Msg 102, Level 15, State 1:
Server 'my_sybase_server', Procedure 'test_trigger', Line 34:
Incorrect syntax near '@colname'.
我做了一些调查,发现第34行意味着以下声明:
if update(@colname)
然后我试着检查1列并用
替换它if update(some_column_name)
这实际上工作正常,我没有任何其他想法如何解决这个问题。看起来update()函数不知何故不允许包含变量。我没有找到有关sybase书籍或谷歌等任何其他地方的任何其他信息。有没有人可以为此找到解决方案?它可能是一个错误吗?是否有光标的变通方法?
感谢您的任何建议
答案 0 :(得分:0)
问题是update(@colname)
类似update('colname')
,需要update(colname)
。为了实现这一目标,您需要使用动态SQL 。
我已经看过the documentation并且可以使用:
动态执行Transact-SQL
当与string或char_variable选项一起使用时,执行连接提供的字符串和变量来执行 生成Transact-SQL命令。这种形式的执行命令可以 用于SQL批处理,过程和触发器。
检查this article以获取有关如何使用动态sql的示例!
答案 1 :(得分:0)
如果每次更改表(添加/删除列)时重新创建触发器都不是问题,您可以使用此类查询生成触发器的主体
select
'if update('+c.name+')
set @colname = '''+c.name+'''
'
from syscolumns c where id = object_id('my_table')