Можно ли получить, если хранимая процедура вызывается внутри другой хранимой процедуры? - PullRequest
1 голос
/ 09 апреля 2019

У меня есть 2 хранимые процедуры, где первая вызывает вторую транзакцию. Вторая процедура никогда не должна вызываться напрямую, а только изнутри ее родителя.

В настоящее время, чтобы проверить, так ли это, я делаю следующее во второй процедуре:

DECLARE @inTran bit;
IF @@TRANCOUNT > 0
    SET @inTran= 0
ELSE
    SET @inTran= 1

Это правильно? Есть ли лучший способ сделать это?

Ответы [ 4 ]

2 голосов
/ 09 апреля 2019

Если вы просто ищете случайный способ предотвратить непреднамеренное выполнение процедуры самостоятельно.Вы также можете проверить @@NESTLEVEL - это будет по крайней мере 2, если вызывается из другого процесса.

CREATE PROCEDURE Child
AS
    IF @@NESTLEVEL < 2 OR @@TRANCOUNT = 0
    THROW 50000, 'Child proc should be called from Parent', 1;

Или вы можете сделать так, чтобы родительский процесс установил значение, прочитанное SESSION_CONTEXT() в дочернем процессе.,

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

0 голосов
/ 09 апреля 2019

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

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

Если «довольно заблокировано» достаточно, предоставьте EXECUTE разрешения на Procedure2 учетной записи службы, в которой вы выполняете свои задания на производстве. По крайней мере, это помешало бы заблудшим пользователям уволить его.

Другая мысль состояла бы в создании пакета служб SSIS с двумя Execute SQL Tasks, в котором первый содержал бы весь код в Procedure1, а второй содержал весь код в Procedure2, затем покончил с процессами и вместо этого запустите пакет. Я не забочусь о внедрении кода в пакеты, потому что обслуживание раздражает.

0 голосов
/ 09 апреля 2019

Для этого вы можете использовать @@ PROCID .Единственная проблема заключается в том, что вам нужно передать параметр на вход.

CREATE PROCEDURE usp_Test1(@id As int)
AS 
PRINT @id
PRINT OBJECT_NAME(@id)
GO 

CREATE PROCEDURE usp_Test2
AS
EXEC usp_Test1 @@PROCID
GO

EXEC usp_Test2
GO

output

1054730910
usp_Test2
0 голосов
/ 09 апреля 2019

Нет надежного способа сделать это. Проверка @@ trancount дает вам информацию только в том случае, если вы участвуете в транзакции или нет, и кто-то может сделать это:

BEGIN TRAN
EXECUTE nested_proc_directly

В этом случае значение счетчика в процедуре будет больше 0. И, как говорили другие, вы не можете использовать стек вызовов. Так что извините.

...