T-SQL存储过程查询sys.database_principals无返回结果的原因
问题原因及解决方法
核心原因
你的存储过程使用了WITH EXECUTE AS OWNER,导致查询执行的上下文发生切换,结合sys.database_principals的权限可见性规则,最终出现无结果的情况:
- 直接执行查询时,你是以当前登录用户的上下文运行,该用户默认能看到自己对应的数据库主体(以及有权限查看的其他主体),因此能返回正确结果。
WITH EXECUTE AS OWNER中的OWNER指的是存储过程所属架构(test)的所有者,而非数据库所有者。当存储过程以该架构所有者的身份执行时,sys.database_principals只会返回该所有者有权限查看的主体。如果架构所有者没有权限查看你传入的principal_id对应的数据库主体,查询自然返回空。
另外,参数名@principal_id与sys.database_principals的列名完全一致,虽然SQL Server通常会优先解析列名,但这种命名方式存在歧义风险,可能在某些场景下导致解析错误。
解决方法
针对上述问题,你可以选择以下任意一种方案:
- 调整执行上下文:如果需要存储过程能查看所有数据库主体,可将
WITH EXECUTE AS OWNER改为WITH EXECUTE AS 'dbo'(dbo默认拥有查看所有数据库主体的权限),或者将test架构的所有者修改为dbo。 - 修改参数名:避免参数名与列名冲突,降低解析歧义,示例代码如下:
Create procedure test.access @target_principal_id int with execute as owner as set nocount on; begin select * from sys.database_principals where principal_id = @target_principal_id end;
- 移除上下文切换:去掉
WITH EXECUTE AS OWNER,让存储过程以调用者的上下文执行,这样就能看到调用者有权限访问的主体。
内容的提问来源于stack exchange,提问作者Phillip Hamilton
相关产品推荐
相关产品推荐

