【发布时间】:2018-05-25 07:33:24
【问题描述】:
在一个 ms sql 数据库中,我有一个名为 combo 的表,其中可以发生多个插入、更新和删除(当然也可以是单个)。在另一个名为 migrimi_temp 的表中,我以查询的形式跟踪这些更改(必须在 mysql 中执行才能获得相同结果的查询)。
例如,如果对 id > 50 的所有行执行删除查询,则应激活触发器以将以下查询存储到日志表中:
从 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 server 版本是 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 天前我完全不熟悉触发器。我正在努力平衡学习与在合理时间内完成,但做得不是很好
【问题讨论】:
-
只要有足够的代码,就可以完成。我不禁认为将光标(已经不是最佳做法)放在触发器内(不是一个很好的做法)会导致很多心痛和糟糕的性能。
标签: tsql sql-server-2012 triggers