2016-03-01 170 views
1

此代码有什么问题。插入更新后的SQL触发器

如果我像这样输入

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].[ax_Triger] ON [dbo].[extraTable] 
FOR INSERT, UPDATE, DELETE AS 

    SET NOCOUNT ON; 
--Capture the Operation (Inserted, Deleted Or Updated) 

    DECLARE @operation int 
    DECLARE @Count AS INT 

    SET @operation = 1 

    SELECT @Count = COUNT(*) 
    FROM DELETED 

    IF @Count > 0 
     BEGIN 
      SET @operation = 3 

      SELECT @Count = COUNT(*) 
      FROM INSERTED 

      IF @Count > 0 
      SET @operation = 2 
     END 
DECLARE tmpUpit CURSOR FOR 
SELECT i.id FROM inserted i 
OPEN tmpUpit 
FETCH NEXT FROM tmpUpit 
into @ID WHILE @@fetch_status = 0 

begin If Not exists 
(SELECT * FROM mytable 
where (Operation=3 OR (Operation=1 AND [email protected])) AND Status = 0 AND Tablename ='extraTable') 

begin INSERT INTO 
mytable ([Field1], [Field2], 
[ID], [Tablename], [Operation], [Time12], [Status]) 
VALUES (@Field1, @Field2, @ID, 'extraTable', @operation,GETDATE(),0) 

DELETE FROM mytable 
WHERE [Field1][email protected] And [Field2][email protected] And [ID][email protected] And [Tablename]='extraTable' 
AND [Operation] = 4 AND [Status] = 0 
End 
FETCH NEXT FROM tmpUpit into @ID 
End CLOSE tmpUpit DEALLOCATE tmpUpit end 

我需要从一个表中插入值到另一个根据有关插入/更新状态/删除

+2

为什么你想要一个游标呢?他们效率非常低下。您尝试的方法将无法正常工作,因为您已经跨越到动态SQL地域。如果你可以发布一些关于你的触发器试图做什么的细节,我们可以帮助你找到一个不需要光标的基于集合的方法。 –

+0

@SeanLange我刚刚编辑..这是我的第一个触发器 – myString

+0

@myString,你可以有条件地声明它,你甚至可以将游标变量作为参数传递给SP。你不需要动态的sql。但不知何故,我认为你需要'完全加入'。 –

回答

1

这是没有经过充分测试,因为贴在表的结构不匹配的贴触发代码。这至少应该证明你可以重新思考这个基于集合的逻辑,而不是通过激动的行来重新考虑行。

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 

在一般情况下,我认为应该避免触发器,但他们有他们的位置。当触发器合适时,我通常不会做这三种操作的狂热粉丝。随着时间的推移,它变得非常混乱,因为你总是需要为不同的操作做不同的逻辑。将它们分成三个触发器使得这种可能性对于维护而言不那么痛苦。