Определить абонента в хранимой процедуре или триггере - PullRequest
1 голос
/ 14 июня 2010

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

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

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

Ответы [ 2 ]

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

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

0 голосов
/ 11 сентября 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, и объединить запрос, аналогичный приведенному выше, с таблицами мониторинга, чтобы найти потенциальных кандидатов, которые необходимо обновить.

...