1

我正在为 SQL Server 2008 R2 编写 CLR 更新触发器。触发器需要将更新的值写入托管在同一 SQL Server 实例中的另一个数据库中的表中。当我尝试从触发器中打开使用以下连接字符串创建的连接时,我收到“SecurityException”:

...new SqlConnection("Data Source=(local);Initial Catalog=[我的数据库];Integrated Security=True")

非常希望我将程序集的权限级别保留为SAFE. 我很确定我必须将程序集的权限级别设置EXTERNAL_ACCESS为连接到远程数据库,但是是否可以使用权限级别连接到同一 SQL Server 实例中的另一个数据库SAFE

谢谢。

4

2 回答 2

2

是的,绝对可以在 SQLCLR 触发器中引用另一个数据库,该触发器位于标记为 的程序集内SAFE。问题中遇到的错误仅仅是由于使用了常规/外部连接字符串,这需要 a PERMISSION_SETof EXTERNAL_ACCESS. 但是使用进程内/内部连接字符串"Context Connection = true;"允许您运行任何您想要的查询,包括通过 3 部分对象名称引用另一个数据库的查询。

我能够使用以下代码做到这一点:

主表(在 TestDB1 中):

CREATE TABLE dbo.Stuff
(
    [Id] INT IDENTITY(1, 1) NOT NULL PRIMARY KEY, 
    [Something] NVARCHAR(50) NOT NULL
);

审计表(在 TestDB2 中):

CREATE TABLE dbo.AuditLog
(
    AuditLogID INT IDENTITY(1, 1) NOT NULL PRIMARY KEY, 
    EventTime DATETIME NOT NULL DEFAULT (GETDATE()),
    BeforeValue NVARCHAR(50) NULL,
    AfterValue NVARCHAR(50) NULL
);

主表上的 SQLCLR 触发器(部分代码):

string _AuditSQL = @"
    INSERT INTO TestDB2.dbo.AuditLog (BeforeValue, AfterValue)
        SELECT del.Something, ins.Something
        FROM   INSERTED ins
        FULL OUTER JOIN DELETED del
                     ON del.Id = ins.Id;
";

SqlConnection _Connection = new SqlConnection("Context Connection = true");
SqlCommand _Command = _Connection.CreateCommand();
_Command.CommandText = _AuditSQL;

try
{
    _Connection.Open();
    _Command.ExecuteNonQuery();
}
finally
{
    _Command.Dispose();
    _Connection.Dispose();
}

测试查询:

USE [TestDB1];
SELECT * FROM dbo.Stuff;
---
INSERT INTO dbo.Stuff (Something) VALUES ('qwerty');
INSERT INTO dbo.Stuff (Something) VALUES ('asdf');

SELECT * FROM dbo.Stuff;
SELECT * FROM TestDB2.dbo.AuditLog;
---
UPDATE  tab
SET     tab.Something = 'dfgdfgdfgdfgdfgdfgd'
FROM    dbo.Stuff tab
WHERE   tab.Id = 2;

SELECT * FROM dbo.Stuff;
SELECT * FROM TestDB2.dbo.AuditLog;
于 2015-06-25T17:27:06.643 回答
0

看起来这是不可能的。但是,T-SQL 语句可以使用 [DatabaseName].[dbo].[TableName] 引用同一实例中的另一个数据库。我可以在我的 CLR 触发器中执行凌乱的逻辑,然后通过调用简单的 T-SQL 存储过程并传入参数来最终插入到第二个数据库中。

于 2012-09-14T05:40:11.387 回答