Sql server 插入更新后的SQL触发器
这个代码有什么问题 如果我像这样打字Sql server 插入更新后的SQL触发器,sql-server,tsql,triggers,Sql Server,Tsql,Triggers,这个代码有什么问题 如果我像这样打字 Declare tmp as CURSOR FOR Select i.ID from Inserted OPEN tmp 或者如果我打字 Declare tmp as CURSOR FOR Select i.ID from Deleted OPEN tmp 很有魅力但是 我有没有办法写这样的东西 if @operation <> 3 set @tmp = 'SELECT i.id FROM inserted i ' else s
Declare tmp as CURSOR FOR
Select i.ID from Inserted
OPEN tmp
或者如果我打字
Declare tmp as CURSOR FOR
Select i.ID from Deleted
OPEN tmp
很有魅力但是
我有没有办法写这样的东西
if @operation <> 3
set @tmp = 'SELECT i.id FROM inserted i '
else
set @tmp =' SELECT i.id FROM deleted i '
DECLARE tmpUpit CURSOR FOR
@tmp
OPEN tmpUpit
我需要根据插入/更新/删除的状态将值从一个表插入到另一个表中,这是完全未测试的,因为发布的表结构与发布的触发代码不匹配。这至少应该说明,您可以将其重新考虑为基于集合的逻辑,而不是一行一行地折磨人
CREATE TRIGGER [dbo].[Trigger212] ON [dbo].[Towns]
FOR INSERT, UPDATE, DELETE AS
BEGIN
SET NOCOUNT ON;
DECLARE @operation int
DECLARE @Variable1 nvarchar(8) = 'Woof'
DECLARE @Variable2 nvarchar(4) = 'Foof'
--Capture the Operation (Inserted, Deleted Or Updated)
IF EXISTS(SELECT * FROM inserted) AND NOT EXISTS (SELECT * FROM deleted)
SET @operation = 1 --Insert
ELSE
IF EXISTS(SELECT * FROM inserted) AND EXISTS (SELECT * FROM deleted)
SET @operation = 2 --update
ELSE
SET @operation = 3 -- DELETE
INSERT Requests
(
Field1
, Field2
, ID
, TableName
, Operation
, TimeU
, Status
)
SELECT 'Woof'
, 'Foof'
, i.ID
, 'Towns'
, @operation
, GETDATE()
, 0
FROM inserted i
LEFT JOIN Requests r on r.ID = i.ID
AND r.Operation = 3
OR (r.Operation = 1 and r.ID = i.ID)
AND r.Status = 0
AND r.TableName = 'Towns'
WHERE r.ID IS NULL
DELETE r
FROM Requests r
JOIN inserted i on i.Field1 = r.Field1
AND i.Field2 = r.Field2
AND i.ID = r.ID
AND i.Operation <> @operation
WHERE r.TableName = 'Towns'
AND r.Status = 0
END
总的来说,我认为应该避免触发器,但它们有它们的位置。当触发器合适时,我通常不太喜欢做这三个操作。随着时间的推移,它变得非常混乱,因为您总是需要为不同的操作执行不同的逻辑。将它们拆分为三个触发器可以大大减少维护的痛苦。为什么您首先需要光标?它们效率极低。您尝试的方法将不起作用,因为您已经进入动态sql领域。如果您可以发布一些关于触发器试图执行的操作的详细信息,我们可以帮助您找到一种不需要光标的基于集合的方法。@SeanLange我刚刚点击了编辑。。这是我的第一次trigger@myString,您可以有条件地声明它,甚至可以将游标变量作为参数传递给SP。您不需要动态sql。但不知何故,我假设您需要完全连接。在任何情况下,您都不希望在触发器中放置游标。从不这很容易以基于集合的方式完成,而且代码行也会更少。这里完全不需要光标。这是两个基本语句,一个insert和一个delete。但是我不能提供太多,因为你没有提供全部的触发。光标之外还有一些额外的标量值。游标中的标量值是一个巨大的红旗,表示内容不基于设置,无法处理多行操作。发布mytable的ddl以及该触发器附加到的任何表,我可以帮助您解决这个问题。
CREATE TRIGGER [dbo].[Trigger212] ON [dbo].[Towns]
FOR INSERT, UPDATE, DELETE AS
BEGIN
SET NOCOUNT ON;
DECLARE @operation int
DECLARE @Variable1 nvarchar(8) = 'Woof'
DECLARE @Variable2 nvarchar(4) = 'Foof'
--Capture the Operation (Inserted, Deleted Or Updated)
IF EXISTS(SELECT * FROM inserted) AND NOT EXISTS (SELECT * FROM deleted)
SET @operation = 1 --Insert
ELSE
IF EXISTS(SELECT * FROM inserted) AND EXISTS (SELECT * FROM deleted)
SET @operation = 2 --update
ELSE
SET @operation = 3 -- DELETE
INSERT Requests
(
Field1
, Field2
, ID
, TableName
, Operation
, TimeU
, Status
)
SELECT 'Woof'
, 'Foof'
, i.ID
, 'Towns'
, @operation
, GETDATE()
, 0
FROM inserted i
LEFT JOIN Requests r on r.ID = i.ID
AND r.Operation = 3
OR (r.Operation = 1 and r.ID = i.ID)
AND r.Status = 0
AND r.TableName = 'Towns'
WHERE r.ID IS NULL
DELETE r
FROM Requests r
JOIN inserted i on i.Field1 = r.Field1
AND i.Field2 = r.Field2
AND i.ID = r.ID
AND i.Operation <> @operation
WHERE r.TableName = 'Towns'
AND r.Status = 0
END