在ms sql数据库中,我有一个名为 combo 的表,其中可能发生多次插入,更新和删除(当然还有单个)。在另一个名为 migrimi_temp 的表中,我以查询的形式跟踪这些更改(查询必须在mysql中执行才能获得相同的结果)。
例如,如果对id> gt的所有行执行删除查询50,触发器应激活以将以下查询存储到日志表中:
DELETE FROM combo,其中id> 50;
因此,组合表中的这一个删除查询将导致日志表中的一行。
但是,如果我有插入2行的插入查询,则应激活触发器以将每个插入存储到日志表中。因此,组合表中的这一个插入查询将导致日志表中的2个新行。
我打算在单独的触发器中处理插入,更新和删除操作。我曾设法为单行插入/更新/删除编写触发器。然后我发现可能还会执行多个操作。
这是我尝试在一个查询中处理多个插入的情况。在没有光标的情况下无法调整初始触发器后,我使用了游标。触发器成功执行,但是当我执行插入(单行或多行)时,执行会无限期挂起,或者至少比合理时间长。
USE [migrimi_test]
GO
/****** Object: Trigger [dbo].[c_combo] Script Date: 12/11/2017 5:33:46 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
create TRIGGER [dbo].[u_combo]
ON [migrimi_test].[dbo].[combo]
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON
DECLARE @c_id INT;
DECLARE @c_name nvarchar(100);
DECLARE @c_duration int;
DECLARE @c_isavailable INT;
DECLARE c CURSOR FOR
SELECT id, name, duration, isvisible FROM inserted
OPEN c
FETCH NEXT FROM c INTO @c_id, @c_name, @c_duration, @c_isavailable
WHILE @@FETCH_STATUS = 0
INSERT INTO [migrimi_temp].[dbo].[sql_query] (query)
VALUES ('INSERT INTO combo (id, name, duration, value, isavailable, createdAt, updatedAt) values ('+CAST(@c_id as nvarchar(50))+', '+'"'+@c_name+'"'+',
'+CAST(@c_duration as nvarchar(50))+', 1, '+CAST(@c_isavailable as nvarchar(50))+', Now(), Now());' )
FETCH NEXT FROM c INTO @c_id, @c_name, @c_duration, @c_isavailable
CLOSE c
END
DEALLOCATE c
GO
SQL服务器版本是2012.操作系统是Windows Server 2008(尽管我怀疑这是相关的)。我主要基于这两个资源:https://social.msdn.microsoft.com/Forums/sqlserver/en-US/40f5635c-9034-4e9b-8fd5-c02cec44ce86/how-to-let-trigger-act-for-each-row?forum=sqlgetstarted
这是我想要完成的更大想法的一部分,直到2天前我对触发器完全不熟悉。我正在努力平衡学习与在合理的时间内完成,但没有做得那么好
答案 0 :(得分:0)
在SQL Server中,游标的速度非常慢。
您可以使用insert...select
这是一种基于集合的方法,而不是使用游标在已插入的表上循环。它更快,是推荐的SQL工作方式:
CREATE TRIGGER [dbo].[u_combo]
ON [migrimi_test].[dbo].[combo]
AFTER INSERT
AS
BEGIN
INSERT INTO [migrimi_temp].[dbo].[sql_query] (query)
SELECT 'INSERT INTO combo (id, name, duration, value, isavailable, createdAt, updatedAt) values ('+CAST(id as nvarchar(50))+', "'+ name +'",
'+ CAST(duration as nvarchar(50)) +', 1, '+ CAST(isvisible as nvarchar(50))+ ', Now(), Now());'
FROM inserted
END
GO