SQL Server OPENROWSET返回空表:嵌套存储过程调用异常
这种情况我之前碰到过几次,大概率是OPENROWSET的会话设置或者结果集元数据识别问题,咱们来逐一排查解决:
确保会话设置在OPENROWSET内部生效
你直接执行时用了SET FMTONLY OFF; SET NOCOUNT ON;,但OPENROWSET是启动一个独立的数据库会话,这些默认设置可能没带上。一定要把这些语句放到OPENROWSET的查询字符串里,同时注意SQL字符串里的单引号需要转义(用两个单引号),之前的双引号也换成单引号(SQL标准字符串用单引号):SELECT * FROM OPENROWSET('SQLNCLI', 'DRIVER={SQL Server};Server=你的服务器地址;Trusted_Connection=yes;', 'SET FMTONLY OFF; SET NOCOUNT ON; EXEC [DbName].[dbo].[usrGetBalanceBystore] @Customer= ''00000000-0000-0000-0000-000000000000'', @Store= ''00000000-0000-0000-0000-000000000000''')另外,确认OPENROWSET使用的登录账号和你直接执行存储过程的账号权限完全一致,包括执行存储过程、访问相关表的权限。
强制指定结果集结构(针对嵌套存储过程的元数据问题)
嵌套存储过程的结果集元数据经常会被OPENROWSET误判,尤其是过程里有动态SQL或条件分支时。可以用WITH RESULT SETS明确指定结果集的列名和数据类型,让OPENROWSET能正确解析数据:SELECT * FROM OPENROWSET('SQLNCLI', 'DRIVER={SQL Server};Server=你的服务器地址;Trusted_Connection=yes;', 'SET FMTONLY OFF; SET NOCOUNT ON; EXEC [DbName].[dbo].[usrGetBalanceBystore] @Customer= ''00000000-0000-0000-0000-000000000000'', @Store= ''00000000-0000-0000-0000-000000000000'' WITH RESULT SETS (( Customer UNIQUEIDENTIFIER, Store UNIQUEIDENTIFIER, Balance DECIMAL(18,2), -- 这里替换成你实际结果集的所有列名和对应数据类型 LastUpdated DATETIME ))')对齐会话的基础设置
有些存储过程的逻辑依赖会话级的设置(比如ANSI_NULLS、QUOTED_IDENTIFIER),直接执行和OPENROWSET的默认设置可能不一致。可以把这些设置也加入到OPENROWSET的查询字符串里,确保和你直接执行时的环境一致:SELECT * FROM OPENROWSET('SQLNCLI', 'DRIVER={SQL Server};Server=你的服务器地址;Trusted_Connection=yes;', 'SET ANSI_NULLS ON; SET QUOTED_IDENTIFIER ON; SET FMTONLY OFF; SET NOCOUNT ON; EXEC [DbName].[dbo].[usrGetBalanceBystore] @Customer= ''00000000-0000-0000-0000-000000000000'', @Store= ''00000000-0000-0000-0000-000000000000''')排查临时表/表变量的影响
如果存储过程里使用了本地临时表(比如#TempTable),OPENROWSET可能无法识别其结果集。可以尝试把本地临时表换成表变量,或者在存储过程里先将结果插入到全局临时表(##TempTable),再在OPENROWSET里查询这个全局临时表,但这种方法需要注意并发问题,优先尝试前面的方案。
内容的提问来源于stack exchange,提问作者NAJEEB

