代码之家  ›  专栏  ›  技术社区  ›  Ed Harper

是否可以确定DML命令是否是从存储过程发出的?

  •  2
  • Ed Harper  · 技术社区  · 14 年前

    我继承了一个SQLServer2008数据库,调用该数据库的应用程序可以通过存储过程访问该数据库。

    对填充审计表的性能测试表明,使用 OUTPUT 子句比使用触发器快20%左右,所以这已经在存储过程中实现了。

    但是,由于这种设计无法通过直接针对表发出的DML语句跟踪直接对表所做的更改,因此还实现了使用 @@NESTLEVEL 确定是否运行触发器(假设所有DML通过存储过程运行都将 @@嵌套级别 &燃气轮机;1).

    IF  @@NESTLEVEL =   1   -- implies call is direct sql so generate history from here
        BEGIN
    ... insert into audit table
    

    这种设计是有缺陷的,因为它不会跟踪在动态SQL中执行DML语句的更新,也不会跟踪在动态SQL中执行DML语句的任何其他上下文 高于1。

    或者这(我怀疑)是不可能的?

    2 回复  |  直到 14 年前
        1
  •  4
  •   KM.    14 年前

    使用 CONTEXT_INFO (Transact-SQL) . 在该过程中,设置一个值以警告触发器不要记录任何内容:

    --in the procedure doing the insert/update/delete
    
    DECLARE @CONTEXT_INFO  varbinary(128)
    SET @CONTEXT_INFO =cast('SkipTrigger=Y'+REPLICATE(' ',128) as varbinary(128))
    SET CONTEXT_INFO @CONTEXT_INFO
    
    --do insert/update/delete that will fire the trigger
    
    SET CONTEXT_INFO 0x0 
    

    在触发器检查上下文中,检查信息并确定是否需要执行任何操作:

    --here is the portion of the trigger to retrieve the value:
    
    IF CAST(CONTEXT_INFO() AS VARCHAR(128))='SkipTrigger=Y'
    BEGIN
        --log your data here
    END
    

        2
  •  0
  •   Cade Roux    14 年前

    我不这么认为。有一个 longstanding Connect item