You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

跨存储过程调用时REVERT为何无法恢复至original_login()?

问题:REVERT语句在跨存储过程调用时的生效范围

我有两个存储过程,Sales.spExec1会调用dbo.spExec2。在dbo.spExec2里执行REVERT语句时,没法恢复到original_login()对应的初始登录身份;但在执行了EXECUTE AS USER的Sales.spExec1里执行REVERT却能正常生效。这是不是意味着REVERT仅在发起身份切换的存储过程内有效?

对应的存储过程代码如下:

CREATE PROCEDURE Sales.spExec1 
AS
BEGIN
    PRINT SUSER_SNAME()  -- 'MyDomain\Bob.Smith'
    PRINT original_login() -- 'MyDomain\Bob.Smith'

    EXECUTE AS USER = 'TempUser';
    EXEC dbo.spExec2

    REVERT;

    /* REVERT works in SP where initial EXECUTE AS USER ran */
    print SUSER_SNAME()  -- 'MyDomain\Bob.Smith'
    print original_login() -- 'MyDomain\Bob.Smith'
END;
GO

CREATE PROCEDURE dbo.spExec2
AS
BEGIN
    PRINT SUSER_SNAME()  -- 'TempUser'
    PRINT original_login() -- 'MyDomain\Bob.Smith'

    REVERT;

    /* REVERT did not work */
    print SUSER_SNAME()   -- Still `TempUser'
    print original_login()
END;
GO

解答

是的,REVERT的生效范围确实和身份切换的上下文绑定,默认情况下,EXECUTE AS 发起的身份切换上下文限定在当前存储过程的执行范围内,跨存储过程调用时,子存储过程没法直接通过REVERT回退到发起切换之前的身份。

具体原因如下:

  • 当你在Sales.spExec1中执行EXECUTE AS USER = 'TempUser'时,SQL Server会创建一个执行上下文栈,这个栈的作用域仅限于当前存储过程的执行上下文。
  • 调用dbo.spExec2时,子存储过程会继承当前的执行身份(TempUser),但它无权操作父存储过程创建的上下文栈。
  • REVERT语句的作用是弹出当前上下文栈的顶部元素,而子存储过程的上下文栈里并没有父存储过程中EXECUTE AS创建的条目,所以执行REVERT不会产生任何效果,身份依然保持为TempUser。

如果需要在子存储过程中也能回退身份,可以参考两种处理方式:

  • 在子存储过程中显式使用EXECUTE AS CALLER(或其他合适的身份切换语句),不过这需要提前规划好权限配置。
  • 把身份切换的逻辑统一放在父存储过程中管理,子存储过程只负责业务逻辑,由父存储过程完成REVERT操作。

内容的提问来源于stack exchange,提问作者fdkgfosfskjdlsjdlkfsf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 22:57:23