确定存储过程或触发器中的调用者

时间:2010-06-14 17:08:06

标签: sql stored-procedures sybase triggers

我正在使用Sybase数据库中的插入触发器。我知道我可以访问@@ nestlevel来确定我是直接调用还是由于另一个触发器或过程。

有没有办法确定,当嵌套级别深于1时,谁执行了导致触发器触发的动作?

例如,表是直接插入的,是否由另一个触发器插入,如果是,则插入哪一个。

2 个答案:

答案 0 :(得分:1)

据我所知,这是不可能的。您最好的选择是将其作为存储过程的参数包含在内。正如here所解释的那样,这也将使您的代码更具可移植性,因为使用的任何方法都可能依赖于某些特定于数据库的调用。那里的链接特定于SQL Server 2005,而不是Sybase,但我认为你几乎就是在同一条船上。

答案 1 :(得分:0)

我自己没有对此进行测试,但假设您使用的是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但嵌套级别&gt;的情况。 1并将类似的查询与上述监控表结合起来,以找到需要更新的潜在候选者。