2010-06-14 65 views
1

我正在使用Sybase数据库中的插入触发器。我知道我可以访问@@ nestlevel来确定我是直接调用还是作为另一个触发器或过程的结果。确定存储过程或触发器内的调用者

有什么办法可以确定,当嵌套层次比1更深时,谁执行引起触发器触发的动作?

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

回答

1

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

+0

这就是我所害怕的。我会看看我能找到什么其他途径来做出决定。 – 2010-06-15 14:34:01

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 [email protected]@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是一个历史性的表格,并且保证只返回一个单独的rown到访问它的任何进程。

如果你没有或者想要设置访问监控表的权限,你可以把这个存储过程传递给@@ procid,@@ spid和@@ nestlevel作为参数。

如果这也不是一个选项,因为您不能将参数传递给触发器,另一个可能的解决方法是使用临时表。

中可能触发这个每个PROC

...

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 

你就会知道它是从内的另一个触发PROC。

这样做的麻烦是它不能“正常工作”。您必须执行临时表设置。 您可以进一步检查以查找没有#trigger_parent但嵌套级别> 1的情况,并将类似的查询与上面的监视表组合在一起,以查找可能需要更新的候选项。