【问题标题】:Determine caller within stored proc or trigger确定存储过程或触发器中的调用者
【发布时间】:2010-06-14 17:08:05
【问题描述】:

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

有什么方法可以确定,当嵌套级别大于 1 时,谁执行了导致触发器触发的操作?

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

【问题讨论】:

    标签: sql stored-procedures sybase triggers


    【解决方案1】:

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

    【讨论】:

    • 这就是我害怕的。我会看看我能找到什么其他途径来做出这个决定。
    【解决方案2】:

    我自己没有对此进行测试,但假设您使用的是 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
    

    你会知道它是从另一个 proc 中触发的。

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

    【讨论】:

      猜你喜欢
      • 2018-01-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-28
      • 1970-01-01
      • 1970-01-01
      • 2023-04-02
      相关资源
      最近更新 更多