Поиск вызывающей функции SQL - PullRequest
5 голосов
/ 28 июня 2010

Есть функция SQL, которую я хотел бы удалить из базы данных SQL Server 2005, но сначала я хотел бы убедиться, что никто не вызывает ее. Я использовал функцию «Просмотр зависимостей», чтобы удалить любую ссылку на нее из базы данных. Однако могут использоваться веб-приложения или пакеты служб SSIS.

Моя идея заключалась в том, чтобы функция вставляла запись в таблицу аудита при каждом ее вызове. Однако это будет иметь ограниченную ценность, если я также не знаю вызывающего абонента. Есть ли способ определить, кто вызвал функцию?

Ответы [ 7 ]

4 голосов
/ 29 июня 2010

Вы можете вызвать расширенные хранимые процедуры из функции .

Вот некоторые примеры:

  • xp_cmdshell
  • xp_regwrite
  • xp_logevent

Ifу вас были правильные разрешения, теоретически вы можете вызывать расширенную хранимую процедуру из своей функции и хранить информацию, такую ​​как APP_NAME () и ORIGINAL_LOGIN (), в простом файле или в ключе реестра.

Другой вариант - создать расширенную хранимую процедуру.хранимая процедура с нуля .

Если все это слишком много проблем, я бы следовал ранней рекомендации SQL Profiler или трассировка на стороне сервера .

Ниже приведен пример использования расширенной хранимой процедуры.При этом 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()
3 голосов
/ 28 июня 2010

попробуйте выполнить поиск по коду:

--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 голосов
/ 28 июня 2010

Вы можете попробовать использовать APP_NAME () и USER_NAME ().Он не даст вам подробностей (например, имя пакета служб SSIS), но может помочь.

2 голосов
/ 28 июня 2010

В зависимости от вашей текущей модели безопасности. Мы используем пул соединений с одной учетной записью sql. Каждое приложение имеет свою учетную запись для подключения к базе данных. Если это так. Затем вы можете выполнить сеанс Sql Profiler, чтобы найти вызывающего эту функцию. Какая бы учетная запись ни вызывала функцию, она будет напрямую связана с одним приложением.

Это работает для нас так, как мы обрабатываем Sql-трафик; Я надеюсь, что это делает то же самое для вас.

1 голос
/ 28 июня 2010

Вы можете запустить трассировку в профилировщике, чтобы увидеть, вызывается ли эта функция в течение недели (или что вы считаете безопасным окном).

Я думаю, что вы также можете использовать OPENROWSET для вызова SP, который регистрирует таблицу, если вы включаете специальные запросы.

1 голос
/ 28 июня 2010

Это поможет вам определить, вызывается ли это где-нибудь в вашей базе данных.

select object_name(id) from sys.syscomments where text like '%**<FunctionName>**%'
1 голос
/ 28 июня 2010

Другой гораздо менее элегантный способ - grep -R [functionname] * через ваш исходный код. Это может или не может быть работоспособным в зависимости от объема кода.

Это имеет преимущество в работе, даже если эта часть используется только очень нечасто, что было бы большой проблемой для вашей идеи таблицы аудита.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...