SQL 游标外的服务器触发操作
SQL Server trigger operation with out cursor
我有一个场景,我必须在每个 DML 操作后生成 SQL 脚本。我们有一个在每次插入、更新、删除后运行的触发器。
主要是它从 Inserted/Deleted table 中获取数据并为每一行生成一个 SQL 脚本并执行插入到另一个 table 中。
例如,如果我们插入
- 获取所有插入的值
- 打开游标
- 对于每个插入的行,生成一个 SQL 脚本,该脚本将被插入到另一个 table 中用于审计目的
- 关闭光标。
对于 5 列的 10,000 行,此触发器需要将近 4-5 个小时。列为 int
、date
和 varchar(100)
.
我们正在尝试更换触发器。需要相同的建议。
Set @syncScript = 'Insert Into table('
Declare insertCursor Cursor Local Forward_Only For
Select a, b, c From Inserted
Open insertCursor
Fetch Next From insertCursor Into @a, @b, @c
While (@@Fetch_Status = 0)
Begin
Declare @valuesList varchar(max)
Set @columnList = ''
Set @paramsList = '['
Set @valuesList = ''
Select @columnList = @columnList + 'col6, ', @paramsList = @paramsList + '''' + COALESCE(dbo.ConvertFloatToVarchar(col6), 'NULL') + ''', ', @valuesList = @valuesList + '?, ' From Inserted I Where I.a= @a And I.b= @b And I.c= @c And 1 = 1
Select @columnList = @columnList + 'col5, ', @paramsList = @paramsList + '''' + COALESCE(Convert(varchar(max), col5), 'NULL') + ''', ', @valuesList = @valuesList + '?, ' From Inserted I Where I.a= @a And I.b= @b And I.c= @c And 1 = 1
Select @columnList = @columnList + 'col4, ', @paramsList = @paramsList + '''' + COALESCE(Convert(varchar(max), col4), 'NULL') + ''', ', @valuesList = @valuesList + '?, ' From Inserted I Where I.a= @a And I.b= @b And I.c= @c And 1 = 1
Select @columnList = @columnList + 'col3, ', @paramsList = @paramsList + '''' + COALESCE(Convert(varchar(max), col3), 'NULL') + ''', ', @valuesList = @valuesList + '?, ' From Inserted I Where I.a= @a And I.b= @b And I.c= @c And 1 = 1
Select @columnList = @columnList + 'col2, ', @paramsList = @paramsList + '''' + COALESCE(Convert(varchar(max), col2), 'NULL') + ''', ', @valuesList = @valuesList + '?, ' From Inserted I Where I.a= @a And I.b= @b And I.c= @c And 1 = 1
Select @columnList = @columnList + 'col1, ', @paramsList = @paramsList + '''' + COALESCE(Convert(varchar(max), col1), 'NULL') + ''', ', @valuesList = @valuesList + '?, ' From Inserted I Where I.TraitValueMemberId = @a And I.ValueSetId = @b And I.LanguageCulture = @c And 1 = 1
Set @columnList = SUBSTRING(@columnList, 1, Len(@columnList) - 1) + ') Values ('
Set @valuesList = SUBSTRING(@valuesList, 1, Len(@valuesList) - 1) + ')'
Set @paramsList = @paramsList + ']'
Set @bigScript = (COALESCE(@syncScript, '') + COALESCE(@columnList, '') + COALESCE(@valuesList, ''))
Insert Into Log (CreatedDate, [Message]) Select GetDate(), 'tablename INSERT syncScript = ' + @bigScript +'paramsList = ' + COALESCE(@paramsList, '')
Insert Into [dbo].[LogAudit] (GuidId, Query, Params, TableName, CreatedDate, Operation, UserId)
Values ('00000000-0000-0000-0000-000000000000', @bigScript, @paramsList, @table, GetDate(), @operation, @debugUser)
Fetch Next From insertCursor Into @a, @b, @c
End
Close insertCursor
Deallocate insertCursor
在更新的情况下,我们连接插入和删除的 tables 以生成如上所示的更新脚本。
我使用 SET 操作而不是触发器解决了这个问题
INSERT Into [dbo].[LogAudit] (GuidId, Query, Params, TableName, CreatedDate, Operation, UserId)
SELECT '00000000-0000-0000-0000-000000000000',
'INSERT INTO Table(col6, col5, col4, col3, col2, col1) VALUES (?, ?, ?, ?, ?, ?)',
'[' + '''' + COALESCE(dbo.ConvertFloatToVarchar(col6), 'NULL') + ''',' + '''' + COALESCE(Convert(varchar(max), col5), 'NULL') + ''', ' + '''' + COALESCE(Convert(varchar(max), col4), 'NULL') + ''', ' + '''' + COALESCE(Convert(varchar(max), col3), 'NULL') + ''', ' + '''' + COALESCE(Convert(varchar(max), col2), 'NULL') + ''', ' + '''' + COALESCE(Convert(varchar(max), col1), 'NULL') + ''', ' + ']', @table, GetDate(), @operation, @debugUser FROM Inserted
-- Insert into Log
Insert Into Log (CreatedDate, [Message]) Select GetDate(), 'MTDE_TraitValueMemberByLanguage_Sync INSERT
syncScript = INSERT Into [dbo].[LogAudit (GuidId, Query, Params, TableName, CreatedDate, Operation, UserId) VALUES VALUES (?, ?, ?, ?, ?, ?)' +
'paramsList = ' + '[' + '''' + COALESCE(dbo.ConvertFloatToVarchar(col6), 'NULL') + ''',' + '''' + COALESCE(Convert(varchar(max), col5), 'NULL') + ''', ' + '''' + COALESCE(Convert(varchar(max), col4), 'NULL') + ''', ' + '''' + COALESCE(Convert(varchar(max), col3), 'NULL') + ''', ' + '''' + COALESCE(Convert(varchar(max), col2), 'NULL') + ''', ' + '''' + COALESCE(Convert(varchar(max), col1), 'NULL') + ''', ' + ']' FROM Inserted
我有一个场景,我必须在每个 DML 操作后生成 SQL 脚本。我们有一个在每次插入、更新、删除后运行的触发器。
主要是它从 Inserted/Deleted table 中获取数据并为每一行生成一个 SQL 脚本并执行插入到另一个 table 中。
例如,如果我们插入
- 获取所有插入的值
- 打开游标
- 对于每个插入的行,生成一个 SQL 脚本,该脚本将被插入到另一个 table 中用于审计目的
- 关闭光标。
对于 5 列的 10,000 行,此触发器需要将近 4-5 个小时。列为 int
、date
和 varchar(100)
.
我们正在尝试更换触发器。需要相同的建议。
Set @syncScript = 'Insert Into table('
Declare insertCursor Cursor Local Forward_Only For
Select a, b, c From Inserted
Open insertCursor
Fetch Next From insertCursor Into @a, @b, @c
While (@@Fetch_Status = 0)
Begin
Declare @valuesList varchar(max)
Set @columnList = ''
Set @paramsList = '['
Set @valuesList = ''
Select @columnList = @columnList + 'col6, ', @paramsList = @paramsList + '''' + COALESCE(dbo.ConvertFloatToVarchar(col6), 'NULL') + ''', ', @valuesList = @valuesList + '?, ' From Inserted I Where I.a= @a And I.b= @b And I.c= @c And 1 = 1
Select @columnList = @columnList + 'col5, ', @paramsList = @paramsList + '''' + COALESCE(Convert(varchar(max), col5), 'NULL') + ''', ', @valuesList = @valuesList + '?, ' From Inserted I Where I.a= @a And I.b= @b And I.c= @c And 1 = 1
Select @columnList = @columnList + 'col4, ', @paramsList = @paramsList + '''' + COALESCE(Convert(varchar(max), col4), 'NULL') + ''', ', @valuesList = @valuesList + '?, ' From Inserted I Where I.a= @a And I.b= @b And I.c= @c And 1 = 1
Select @columnList = @columnList + 'col3, ', @paramsList = @paramsList + '''' + COALESCE(Convert(varchar(max), col3), 'NULL') + ''', ', @valuesList = @valuesList + '?, ' From Inserted I Where I.a= @a And I.b= @b And I.c= @c And 1 = 1
Select @columnList = @columnList + 'col2, ', @paramsList = @paramsList + '''' + COALESCE(Convert(varchar(max), col2), 'NULL') + ''', ', @valuesList = @valuesList + '?, ' From Inserted I Where I.a= @a And I.b= @b And I.c= @c And 1 = 1
Select @columnList = @columnList + 'col1, ', @paramsList = @paramsList + '''' + COALESCE(Convert(varchar(max), col1), 'NULL') + ''', ', @valuesList = @valuesList + '?, ' From Inserted I Where I.TraitValueMemberId = @a And I.ValueSetId = @b And I.LanguageCulture = @c And 1 = 1
Set @columnList = SUBSTRING(@columnList, 1, Len(@columnList) - 1) + ') Values ('
Set @valuesList = SUBSTRING(@valuesList, 1, Len(@valuesList) - 1) + ')'
Set @paramsList = @paramsList + ']'
Set @bigScript = (COALESCE(@syncScript, '') + COALESCE(@columnList, '') + COALESCE(@valuesList, ''))
Insert Into Log (CreatedDate, [Message]) Select GetDate(), 'tablename INSERT syncScript = ' + @bigScript +'paramsList = ' + COALESCE(@paramsList, '')
Insert Into [dbo].[LogAudit] (GuidId, Query, Params, TableName, CreatedDate, Operation, UserId)
Values ('00000000-0000-0000-0000-000000000000', @bigScript, @paramsList, @table, GetDate(), @operation, @debugUser)
Fetch Next From insertCursor Into @a, @b, @c
End
Close insertCursor
Deallocate insertCursor
在更新的情况下,我们连接插入和删除的 tables 以生成如上所示的更新脚本。
我使用 SET 操作而不是触发器解决了这个问题
INSERT Into [dbo].[LogAudit] (GuidId, Query, Params, TableName, CreatedDate, Operation, UserId)
SELECT '00000000-0000-0000-0000-000000000000',
'INSERT INTO Table(col6, col5, col4, col3, col2, col1) VALUES (?, ?, ?, ?, ?, ?)',
'[' + '''' + COALESCE(dbo.ConvertFloatToVarchar(col6), 'NULL') + ''',' + '''' + COALESCE(Convert(varchar(max), col5), 'NULL') + ''', ' + '''' + COALESCE(Convert(varchar(max), col4), 'NULL') + ''', ' + '''' + COALESCE(Convert(varchar(max), col3), 'NULL') + ''', ' + '''' + COALESCE(Convert(varchar(max), col2), 'NULL') + ''', ' + '''' + COALESCE(Convert(varchar(max), col1), 'NULL') + ''', ' + ']', @table, GetDate(), @operation, @debugUser FROM Inserted
-- Insert into Log
Insert Into Log (CreatedDate, [Message]) Select GetDate(), 'MTDE_TraitValueMemberByLanguage_Sync INSERT
syncScript = INSERT Into [dbo].[LogAudit (GuidId, Query, Params, TableName, CreatedDate, Operation, UserId) VALUES VALUES (?, ?, ?, ?, ?, ?)' +
'paramsList = ' + '[' + '''' + COALESCE(dbo.ConvertFloatToVarchar(col6), 'NULL') + ''',' + '''' + COALESCE(Convert(varchar(max), col5), 'NULL') + ''', ' + '''' + COALESCE(Convert(varchar(max), col4), 'NULL') + ''', ' + '''' + COALESCE(Convert(varchar(max), col3), 'NULL') + ''', ' + '''' + COALESCE(Convert(varchar(max), col2), 'NULL') + ''', ' + '''' + COALESCE(Convert(varchar(max), col1), 'NULL') + ''', ' + ']' FROM Inserted