是的,绝对可以在 SQLCLR 触发器中引用另一个数据库,该触发器位于标记为 的程序集内SAFE
。问题中遇到的错误仅仅是由于使用了常规/外部连接字符串,这需要 a PERMISSION_SET
of 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;