了解在用户定义的函数中不允许使用副作用运算符(如"insert"),如何记录(或以其他方式跟踪)对特定用户定义函数的调用?我还想捕获传递给UDF的参数.
理想情况下,日志将是一个表,其中插入了有关每次UDF调用的信息(时间戳和参数值).然后可以从该表派生报告和使用度量.
我不能将UDF重写为存储过程,即使是同名,也不会破坏许多期望UDF并且我无法控制的下游系统.
我也不愿意在我们的服务器上启用任何类型的命令shell功能,这将降低SQL Server的最佳实践安全默认值.
我找到了你的问题的解决方案.它有点棘手,看起来像黑客,但似乎不可能以另一种方式解决.
我们的想法是创建一个.NET SQL函数,在需要的地方记录数据(文件,Windows EventLog,db等),然后创建调用此.NET函数的SQL UDF,最后通过函数调用此SQL函数传递所有参数需要记录.SQL Server不检查.net函数内部是什么,你可以在那里写下你需要的所有逻辑.
如何没有任何安全限制创建.NET SQL函数的概念是从其中取出后.
因此,使用这个文件创建一个.net库项目
using System;
namespace SqlTest
{
public class LogEvent
{
[Microsoft.SqlServer.Server.SqlFunction]
public static int Log(string data)
{
System.IO.File.AppendAllText(@"C:\Log\LogUDF.txt", data);
return 0;
}
}
}
使用一些pfx证书(项目属性 - >签名选项卡)对其进行签名.
接下来,调用此查询
USE [master]
CREATE ASYMMETRIC KEY LogKey FROM EXECUTABLE FILE =
'C:\Work\ConsoleApplication1\SqlTest\bin\Debug\SqlTest.dll'
CREATE LOGIN LogLogin FROM ASYMMETRIC KEY LogKey
GRANT UNSAFE ASSEMBLY TO LogLogin
GO
USE [MyDB]
CREATE ASSEMBLY SqlTest FROM
'C:\Work\ConsoleApplication1\SqlTest\bin\Debug\SqlTest.dll'
WITH PERMISSION_SET = unsafe
GO
CREATE FUNCTION dbo.Log( @data as nvarchar(200) )
RETURNS int
AS EXTERNAL NAME SqlTest.[SqlTest.LogEvent].Log
在这里,您需要更改已编译库的路径,MyDB - 您的数据库名称.并且您将创建dbo.Log SQL函数.接下来,您可以在需要的地方拨打电话.例如,从这个TestFunction
CREATE FUNCTION TestFunction
(
@p1 int
)
RETURNS int
AS
BEGIN
DECLARE @temp int
SELECT @temp = [dbo].[Log] ('fff')
RETURN 1
END
因此,调用SELECT TestFunction(1)
将'fff'
文本写入C:\Log\LogUDF.txt
文件.
而已.一些重要的注意事项:
SQL Server应具有写入文件的权限(登录/用户)C:\Log\LogUDF.txt
.
你应该是SQL服务器管理员