Нахождение вызывающей стороны функции SQL

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

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

5
задан Eric Ness 28 June 2010 в 14:16
поделиться

7 ответов

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

--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 в разных местах, вы можете сузить круг тех, кто вызывает функцию , и уточняйте значение, пока не найдете его.

3
ответ дан 18 December 2019 в 13:10
поделиться

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

Вот несколько примеров:

  • xp_cmdshell
  • xp_regwrite
  • xp_logevent

Если у вас были правильные разрешения, теоретически вы могли бы вызвать расширенную хранимую процедуру из своей функции и сохранить такую ​​информацию, как 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()
4
ответ дан 18 December 2019 в 13:10
поделиться

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

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

2
ответ дан 18 December 2019 в 13:10
поделиться

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

2
ответ дан 18 December 2019 в 13:10
поделиться

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

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

1
ответ дан 18 December 2019 в 13:10
поделиться

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

select object_name(id) from sys.syscomments where text like '%**<FunctionName>**%'
1
ответ дан 18 December 2019 в 13:10
поделиться

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

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

1
ответ дан 18 December 2019 в 13:10
поделиться