2008-09-29 4 views
16

Возможно ли узнать, кто вызвал процедуру хранения?Выяснить вызывающую хранимую процедуру в SQL Server

Например, я получаю сообщение об ошибке proc3. Изнутри этого proc я хочу знать, был ли он вызван proc1 или proc2.

+6

Вы можете узнать имя текущего SP, получив `OBJECT_NAME (@@ PROCID)` – Gman 2010-05-08 15:39:11

ответ

8

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

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

3

Нужно ли вам знать в proc3 во время выполнения, которое вызвало ошибку, или вам просто нужно знать во время отладки?

Вы можете использовать SQL Server profiler, если вам нужно только это сделать во время отладки/мониторинга.

В противном случае в 2005 году я не считаю, что у вас есть возможность отслеживать трассировку.

Чтобы обойти это, вы можете добавить дополнительный параметр в proc3, @CallingProc или что-то в этом роде.

ИЛИ вы можете добавить блоки захвата try к proc1 и proc2.

BEGIN TRY 
EXEC Proc3 
END TRY 
BEGIN CATCH 
SELECT 'Error Caught' 
SELECT 
    ERROR_PROCEDURE() 
END CATCH 

Хорошая ссылка здесь: http://searchsqlserver.techtarget.com/tip/1,289483,sid87_gci1189087,00.html

и, конечно, всегда SQL Server Books Online

SQL Server 2008 имеет возможность отладки с помощью процедур, однако.

2

Вы могли бы передать proc1 и proc2 свои имена в proc3 в качестве параметра.

Например:

CREATE PROCEDURE proc3 
    @Caller nvarchar(128) -- Name of calling proc. 
    AS 
    BEGIN 
    -- Produce error message that includes caller's name. 
    RAISERROR ('Caller was %s.', 16,10, @Caller); 
    END 
    GO 

    CREATE PROCEDURE proc1 
    AS 
    BEGIN 
    -- Get the name of this proc. 
    DECLARE @ProcName nvarchar(128); 
    SET @ProcName = OBJECT_NAME(@@PROCID); 
    -- Pass it to proc3. 
    EXEC proc3 @ProcName 
    END 
    GO 

    CREATE PROCEDURE proc2 
    AS 
    BEGIN 
    -- Get the name of this proc. 
    DECLARE @ProcName nvarchar(128); 
    SET @ProcName = OBJECT_NAME(@@PROCID); 
    -- Pass it to proc3. 
    EXEC proc3 @ProcName 
    END 
    GO 
3

Там нет хорошего автоматического способа сделать это (увы). Так что это действительно зависит от того, насколько вы готовы (запишите) свои procs, чтобы иметь возможность сделать это.

Если у вас есть механизм регистрации, вы можете прочитать журнал и выяснить, кто звонил вам.

Например, если реализовать протоколирование, вставив в таблицу, например:

CREATE TABLE Log 
(timestamp dattime, 
spid  int, 
procname varchar(255), 
message varchar(255)) 

... text of proc ... 
INSERT INTO Log 
SELECT get_date(), @@spid, @currentproc, 'doing something' 
-- you have to define @currentproc in each proc 

-- get name of caller 
SELECT @caller = procname 
FROM Log 
WHERE spid = @@spid 
AND timestamp = (SELECT max(timestamp) 
        FROM Log 
        WHERE timestamp < get_date() 
        AND procname != @currentproc) 

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