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

时间:2010-07-28 16:59:43

标签: sql-server triggers sqlclr

我想在SQL CLR触发器中打开/关闭触发器递归。根据{{​​3}},我必须致电

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

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

此致

3 个答案:

答案 0 :(得分:1)

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

CREATE TRIGGER etc
....
GO
DECLARE @db varchar(100)
SET @db = DB_NAME()
EXEC sp_dboption @db, 'recursive triggers', 'true'/'false'

答案 1 :(得分:1)

有一种非常简单的方法可以找到触发SQLCLR触发器的数据库的名称:只需建立与Context Connection的连接并获取Database属性。您甚至不需要执行查询: - )。

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

string _DatabaseName;

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

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

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

在SQLCLR中仍然可以使用它,但如果没有触发器的名称,则只能限制所有触发器。这意味着,您可以阻止任何触发器在任何表上触发任何其他触发器,包括在同一个表上,但是在允许其他表上的触发器的同时,无法限制触发相同的触发器可能会被相关的触发器修改。只需使用Context Connection并通过SELECT TRIGGER_NESTLEVEL();运行SqlCommand.ExecuteScalar()

答案 2 :(得分:0)

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

我必须完全避免调用EXEC sp_dboption。相反,我必须创建一个临时表作为标志“无递归”,然后检查触发器开始时表的存在并退出,如果表存在。

为何选择临时表?

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