Определить вызывающего абонента в хранимой процедуре или триггере

Я работаю с триггером вставки в базе данных Sybase. Я знаю, что могу получить доступ к @@nestlevel, чтобы определить, вызываются ли меня напрямую или в результате другого триггера или процедуры.

Есть ли способ определить, когда уровень вложенности глубже 1, кто выполнил действие, вызвавшее срабатывание триггера?

Например, была ли таблица вставлена ​​напрямую, была ли она вставлена ​​другим триггером и если да, то каким.


person Mike Clark    schedule 14.06.2010    source источник


Ответы (2)


Насколько я знаю, это невозможно. Лучше всего включить его в качестве параметра в ваши хранимые процедуры. Как объясняется здесь, это также сделает ваш код более переносимым, поскольку любой используемый метод, скорее всего, будет зависеть от некоторого вызова, специфичного для базы данных. Ссылка была специфична для SQL Server 2005, а не для Sybase, но я думаю, что вы в значительной степени находитесь в одной лодке.

person Tom H    schedule 14.06.2010
comment
Вот чего я боялся. Я посмотрю, какой другой путь я могу найти, чтобы принять это решение. - person Mike Clark; 15.06.2010

Я не проверял это сам, но если вы используете Sybase ASE 15.03 или более позднюю версию, у вас включены таблицы мониторинга monProcessStatement и monSysStatement и установлены соответствующие разрешения, позволяющие получить к ним доступ из вашего триггера, вы можете попробовать...

declare @parent_proc_id int
if @@nestlevel > 1
begin

   create table #temp_parent_proc (
    procId int,
    nestLevel int,
    contextId int
   )
   insert into #temp_parent_proc
    select  mss.ProcedureID,
            mss.ProcNestLevel,
            mss.ContextID
    from monSysStatement mss 
    join monProcessStatement mps
        on mss.KPID = mps.KPID
        and mss.BatchID = mps.BatchID
        and mss.SPID = mps.SPID
    where mps.ProcedureID =@@procid
        and mps.SPID = @@spid

    select @parent_proc_id = (select tpp.procId
                from #temp_parent_proc tpp,
                     #temp_parent_proc2 tpp2
                where tpp.nestLevel = tpp2.nestLevel-1
                  and tpp.contextId < tpp2.contextId
                  and tpp2.procId = @@procid
                  and tpp2.nestLevel = @@nestlevel
                group by tpp.procId, tpp.contextId
                having tpp.contextId = max(tpp.contextId ))

    drop table #temp_parent_proc
end

Временная таблица необходима из-за природы monProcessStatement и monSysStatement. monProcessStatement является временным, поэтому, если вы ссылаетесь на него более одного раза, он может больше не содержать одни и те же строки. monSysStatement — это историческая таблица, которая гарантированно возвращает отдельную строку только один раз любому процессу, обращающемуся к ней.

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

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

в каждом процессе, который может вызвать это...

create table #trigger_parent (proc_id int)
insert into #trigger_parent @@procid

то в вашем триггере будет доступна временная таблица...

if object_id('#trigger_parent') is not null 
    set @parent_proc = select l proc_id from #trigger_parent

вы будете знать, что он был запущен из другого процесса.

Проблема в том, что это не «просто работает». Вы должны обеспечить настройку временной таблицы. Вы можете выполнить дополнительную проверку, чтобы найти случаи, когда #trigger_parent отсутствует, но уровень вложенности > 1, и объединить аналогичный запрос с таблицами мониторинга, как указано выше, чтобы найти потенциальных кандидатов, которые необходимо обновить.

person Mr.Mindor    schedule 10.09.2010