sp_describe_first_result_set遇REVERT失败,如何获取调用方数据库主体?
解决sp_describe_first_result_set遇到REVERT无法获取元数据的问题
方案1:将调用方用户获取逻辑封装到单独存储过程
把需要切换到CALLER上下文的逻辑抽离到独立的、带有WITH EXECUTE AS CALLER的存储过程中,主存储过程无需自行执行EXECUTE AS和REVERT,从而避开元数据检测对REVERT的限制。
示例代码:
-- 封装获取调用方用户的存储过程 CREATE OR ALTER PROCEDURE sp_GetCallerUserName WITH EXECUTE AS CALLER AS BEGIN SELECT USER_NAME() AS CallerUserName; END GO -- 主存储过程 CREATE OR ALTER PROCEDURE spTest WITH EXECUTE AS OWNER AS BEGIN DECLARE @name sysname; -- 调用封装的存储过程获取调用方用户 SELECT @name = CallerUserName FROM sp_GetCallerUserName(); SELECT 'Hello ' + @name AS Msg; END GO -- 现在可以正常获取元数据 EXEC sp_describe_first_result_set N'EXEC spTest', NULL, 0
方案2:条件执行REVERT(依赖内部函数)
利用SQL Server内部函数sys.fn_MSis_meta_function_call()判断当前是否处于元数据检测上下文,仅在非检测时执行REVERT,避免元数据分析时触发错误。
示例代码:
CREATE OR ALTER PROCEDURE spTest WITH EXECUTE AS OWNER AS BEGIN DECLARE @name sysname; EXECUTE AS CALLER; SELECT @name = USER_NAME(); -- 仅非元数据检测场景执行REVERT IF NOT sys.fn_MSis_meta_function_call() BEGIN REVERT; END SELECT 'Hello ' + @name AS Msg; END GO EXEC sp_describe_first_result_set N'EXEC spTest', NULL, 0
方案3:直接通过系统视图获取调用方数据库用户
无需上下文切换,通过关联系统视图从登录名映射到当前数据库的用户主体:
CREATE OR ALTER PROCEDURE spTest WITH EXECUTE AS OWNER AS BEGIN DECLARE @name sysname; -- 通过登录名关联当前数据库用户 SELECT @name = dp.name FROM sys.server_principals sp JOIN sys.database_principals dp ON sp.sid = dp.sid WHERE sp.name = ORIGINAL_LOGIN(); SELECT 'Hello ' + @name AS Msg; END GO EXEC sp_describe_first_result_set N'EXEC spTest', NULL, 0
注意:此方法依赖登录名与数据库用户的SID匹配,若调用方登录名未在当前数据库映射对应用户会返回NULL,需额外处理边界情况。
内容的提问来源于stack exchange,提问作者Ola Berntsson
相关产品推荐
相关产品推荐

