我想从SQL Server 2005数据库中删除一个SQL函数,但首先我要确保没有人调用它。我已经使用“查看依赖项”功能从数据库中删除对它的任何引用。但是,可能有Web应用程序或SSIS包使用它。
我的想法是让函数在每次调用时在审计表中插入一条记录。但是,除非我也知道呼叫者,否则这将是有限的价值。有没有办法确定谁调用了这个函数?
答案 0 :(得分:4)
您可以从extended stored procedures致电function。
一些例子是:
如果您拥有正确的权限,理论上您可以从函数中调用扩展存储过程,并将APP_NAME()和ORIGINAL_LOGIN()等信息存储在平面文件或注册表项中。
另一种选择是从scratch构建扩展存储过程。
如果这一切都太麻烦,我会遵循SQL Profiler的早期建议或server side tracing。
下面是使用扩展存储过程的示例。这使用xp_logevent记录Windows应用程序日志中的每个函数调用实例。
此方法的一个警告是,如果函数应用于SELECT查询中的列,则将为返回的每一行调用该函数。这意味着您可以快速填写日志。
代码:
USE [master]
GO
/* A security risk but will get the job done easily */
GRANT EXECUTE ON xp_logevent TO PUBLIC
GO
/* Test database */
USE [Sandbox]
GO
/* Test function which always returns 1 */
CREATE FUNCTION ufx_Function() RETURNS INT
AS
BEGIN
DECLARE
@msg VARCHAR(4000),
@login SYSNAME,
@app SYSNAME
/* Gather critical information */
SET @login = ORIGINAL_LOGIN()
SET @app = APP_NAME()
SET @msg = 'The function ufx_Function was executed by '
+ @login + ' using the application ' + @app
/* Log this event */
EXEC master.dbo.xp_logevent 60000, @msg, warning
/* Resume normal function */
RETURN 1
END
GO
/* Test */
SELECT dbo.ufx_Function()
答案 1 :(得分:3)
尝试此搜索代码:
--declare and set a value of @SearchValue to be your function name
SELECT DISTINCT
s.name+'.'+o.name AS Object_Name,o.type_desc
FROM sys.sql_modules m
INNER JOIN sys.objects o ON m.object_id=o.object_id
INNER JOIN sys.schemas s ON o.schema_id=s.schema_id
WHERE m.definition Like '%'+@SearchValue+'%'
ORDER BY 1
要在运行时查找调用方,您可以尝试使用CONTEXT_INFO
--in the code chain doing the suspected function call:
DECLARE @CONTEXT_INFO varbinary(128)
,@Info varchar(128)
SET @Info='????'
SET @CONTEXT_INFO =CONVERT(varbinary(128),'InfoForFunction='+ISNULL(@Info,'')+REPLICATE(' ',128))
SET CONTEXT_INFO @CONTEXT_INFO
--after the suspected function call
SET CONTEXT_INFO 0x0 --reset CONTEXT_INFO
--here is the portion to put in the function:
DECLARE @Info varchar(128)
,@sCONTEXT_INFO varchar(128)
SET @sCONTEXT_INFO=CONVERT(varchar(128),CONTEXT_INFO())
IF LEFT(@sCONTEXT_INFO,15)='InfoForFunction='
BEGIN
SET @Info=RIGHT(RTRIM(@sCONTEXT_INFO),LEN(RTRIM(@sCONTEXT_INFO))-15)
END
--use the @Info
SELECT @Info,@sCONTEXT_INFO
如果你在不同的地方在@CONTEXT_INFO中添加不同的值,你可以缩小调用该函数的人的范围,并在找到之前优化该值。
答案 2 :(得分:2)
取决于您当前的安全模型。我们使用连接池与一个SQL帐户。每个应用程序都有自己的帐户来连接数据库。如果是这样的话。然后,您可以执行Sql Profiler会话以查找该函数的调用者。无论哪个帐户调用该函数都将直接与一个应用程序相关。
这对我们处理Sql流量的方式起作用;我希望它能为你做同样的事。
答案 3 :(得分:2)
您可以尝试使用APP_NAME()和USER_NAME()。它不会给你详细信息(如SSIS包名称),但它可能有所帮助。
答案 4 :(得分:1)
另一个不那么优雅的方法是通过源代码grep -R [functionname] *
。根据代码的数量,这可能是可行的,也可能是不可行的。
这样做的好处就是工作即使只使用非常的部分,这对你的审计表的想法来说也是个大问题。
答案 5 :(得分:1)
这将帮助您查找是否在数据库中的任何位置调用此方法。
select object_name(id) from sys.syscomments where text like '%**<FunctionName>**%'
答案 6 :(得分:1)
您可以在探查器中运行跟踪,以查看该函数是否被调用一周(或您认为是安全窗口的任何内容)。
我认为如果启用即席查询,您也可以使用OPENROWSET来调用记录到表的SP。