代码之家  ›  专栏  ›  技术社区  ›  noober

SQL CLR触发器:上下文数据库的名称

  •  1
  • noober  · 技术社区  · 15 年前

    我想在我的SQLCLR触发器中打开/关闭触发器递归。根据 http://www.devx.com/tips/Tip/30031 ,我得打电话

    EXEC sp_dboption '<name of db>', 'recursive triggers', 'true'/'false'
    

    有没有办法知道当前数据库名称是什么?创建触发器时,我要求用户选择一个触发器,但我不想将其写入表中。

    当做,

    3 回复  |  直到 10 年前
        1
  •  1
  •   Solomon Rutzky    10 年前

    有一种非常简单的方法来查找在其中触发sqlcr触发器的数据库的名称:只需连接到上下文连接并获取 Database 财产。您甚至不需要执行查询:-)。

    以下内容应适用于所有SQLCLR对象类型(存储过程、函数、用户定义的聚合、用户定义的类型和触发器):

    string _DatabaseName;
    
    using (SqlConnection _Connection = new SqlConnection("Context Connection = true;"))
    {
        _Connection.Open();
        _DatabaseName = _Connection.Database;
    }
    

    就是这样!我只是在一个sqlcr触发器中尝试过,效果很好。


    另一件需要记住的事情是,限制触发其他触发器的触发器是 TRIGGER_NESTLEVEL 功能。这在T-SQL触发器中效果更好,其中 @@PROCID 提供并包含 [object_id] 触发。因此,在T-SQL触发器中,您可以单独限制每个触发器的递归,但仍然允许触发器在其他表上触发其他触发器。

    在sqlcr中,它仍然可以使用,但是如果没有触发器的名称,则只能限制所有触发器。也就是说,您可以防止任何触发器在任何表上(包括同一表上)触发任何其他触发器,但无法限制 只有 同一触发器,同时允许其他表上的触发器可能被相关触发器修改。只需使用上下文连接并运行 SELECT TRIGGER_NESTLEVEL(); 通过 SqlCommand.ExecuteScalar() .

        2
  •  1
  •   gbn    15 年前

    您知道创建触发器时数据库是什么…

    CREATE TRIGGER etc
    ....
    GO
    DECLARE @db varchar(100)
    SET @db = DB_NAME()
    EXEC sp_dboption @db, 'recursive triggers', 'true'/'false'
    
        3
  •  0
  •   noober    15 年前

    我找到了更好的解决方案。

    我必须避免调用exec sp_dboption。相反,我必须创建一个临时表作为“no recursion”标志,然后在触发器开始时检查该表的现有性,如果该表存在,则退出。

    为什么是临时桌?

    1. 在会议结束时就被杀了。无需重置标志(在特殊情况下),否则必须避免永久关闭触发器。
    2. 阿法克,它是为每一个连接独立地被创造和杀死的。因此,如果用户同时更改数据,则不会发生冲突(这对于exec sp_dboption是不可避免的)。