Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 插入更新后的SQL触发器_Sql Server_Tsql_Triggers - Fatal编程技术网

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