【问题标题】:Pass a variable into a trigger将变量传递给触发器
【发布时间】:2020-07-10 16:43:33
【问题描述】:

我有一个trigger,它处理一些用于记录目的的数据,如下所示:

CREATE TRIGGER trgDataUpdated
   ON tblData FOR UPDATE
AS 
BEGIN
    INSERT INTO tblLog ( ParentID, OldValue, NewValue, UserID )
    SELECT  deleted.ParentID, deleted.Value, inserted.Value, 
            @intUserID -- how can I pass this in?
    FROM    inserted INNER JOIN deleted ON inserted.ID = deleted.ID
END

如何将变量@intUserID 传入上述触发器,如下代码:

DECLARE @intUserID int
SET @intUserID = 10

UPDATE tblData
SET    Value = @x

PS:我知道我不能直接将@intUserID 传递给触发器,它只是用于说明目的。

【问题讨论】:

    标签: sql-server tsql variables triggers sql-server-2000


    【解决方案1】:

    我使用SET CONTEXT_INFO 进行这种操作。这是一个 2008 年以上的链接,prior link 已停用。

    在 SQL Server 2005+ 上,您必须使用 CONTEXT_INFO 来阅读它,否则您必须从 dbo.sysprocesses 中的 context_info 列中获取。

    【讨论】:

    • 我正在考虑这个,但它看起来不是最优雅的解决方案。如果这是唯一的方法,那么我肯定会这样做,但我希望有别的方法:(
    • 我现在正在实施这个。只是想将此链接粘贴给其他想要在未来这样做的人:msdn.microsoft.com/en-us/library/aa214382%28SQL.80%29.aspx
    【解决方案2】:

    您不能将变量传递给触发器。

    在触发器中获取信息的唯一方法是能够根据 INSERTED 或 DELETED 表选择它,或者在受影响的表中添加一列并将值放入该列中。

    EDIT 在上一个问题 OP 发布的关于此的问题中,他们说他们不想使用 CONTEXT_INFO,但在这里他们说可以使用,所以这里是一个 CONTEXT_INFO 用法示例:

    在更新过程中

    DECLARE @intUserID     int
           ,@CONTEXT_INFO  varbinary(128)
    SET @intUserID = 10
    SET @CONTEXT_INFO =cast('intUserID='+CONVERT(varchar(10),@intUserID)+REPLICATE(' ',128) as varbinary(128))
    SET CONTEXT_INFO @CONTEXT_INFO
    
    --do update that will fire the trigger
    
    SET CONTEXT_INFO 0x0 
    

    这里是获取值的触发器部分:

    DECLARE @intUserID     int
           ,@sCONTEXT_INFO  varchar(128)
    SELECT @sCONTEXT_INFO=CAST(CONTEXT_INFO() AS VARCHAR) FROM master.dbo.SYSPROCESSES WHERE SPID=@@SPID
    
    IF LEFT(@sCONTEXT_INFO,9)='intUserID'
    BEGIN
        SET @intUserID=RIGHT(RTRIM(@sCONTEXT_INFO),LEN(RTRIM(@sCONTEXT_INFO))-10)
    END
    ELSE
    BEGIN
        RAISERROR('intUserID was not specified',16,1)
        ROLLBACK TRAN
        RETURN
    END
    
    ..use the @intUserID
    

    【讨论】:

      【解决方案3】:

      老问题,但我想知道为什么没有人提到在触发器被调用之前创建的临时表在触发器中是可见的? 所以,这会起作用:

      SELECT 10 intUserID INTO #intUserID
      
      UPDATE tblData
      SET    Value = @x
      

      触发器将看到临时表 #intUserID 并可以从那里读取 id。

      【讨论】:

        【解决方案4】:

        我使用 sp_set_session_context 存储过程来设置值:

        exec sp_set_session_context @key = N'userid', @value = 123 
        

        并在我的触发器中读取值:

        DECLARE @userid int
        SELECT @userid = cast(SESSION_CONTEXT(N'userid') as int)
        

        【讨论】:

          【解决方案5】:

          您不能将变量传递给触发器。根据用户连接到数据库的方式,您可以使用SYSTEM_USER 让当前用户连接到数据库。

          【讨论】:

            【解决方案6】:

            您不会将变量传递给触发器,因为您无法直接调用触发器。它们是由于数据被插入、修改或删除而执行的。

            【讨论】:

            • 我不是在这里寻找是/否的答案。肯定有一种方法可以存储触发器可以获取的当前事务的信息吗?
            【解决方案7】:

            为什么不试试这个:

            CREATE TRIGGER trgDataUpdated
               ON tblData FOR UPDATE
            AS 
            BEGIN
                EXECUTE tbLogUpdate intUserId
            END
            

            【讨论】:

            • 这怎么能工作,因为你甚至没有传递或声明'intUserId'?投反对票
            • 对近十年前的某些东西投反对票。过了这么久我就不讨论这个了。如果有人想删除答案,请随意
            • 确切地说是 7 年前。感觉很喜欢。
            • 对更接近十年前的投票投反对票。同样,'intUserId' 来自哪里?
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2018-03-08
            • 1970-01-01
            • 2013-10-26
            • 1970-01-01
            • 1970-01-01
            • 2022-01-03
            • 2016-05-12
            相关资源
            最近更新 更多