首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

SQL Server 將存儲過程結果集插入臨時表:OPENQUERY + EXEC 模式

     編輯:MySQL 資料庫相關知識

需將存儲過程返回的結果集作為數據源進一步查詢(如篩選、連接、聚合),直接 INSERT INTO #Temp EXEC sp_Name 在舊版本有限制。通過 OPENQUERY 繞過限制,實現結果集物化。本文給出標準模式與前置配置。

前置配置:啟用數據訪問

-- 必須在鏈接服務器(含本地環回)啟用 Data Access
EXEC sp_serveroption 'LocalServerName', 'Data Access', 'True';
若報錯「伺服器 '...' 未配置數據訪問」,執行上述命令後重新嘗試。

標準模式:SELECT INTO #Temp FROM OPENQUERY

-- 1. 將存儲過程結果集導入臨時表
SELECT * INTO #TmpWho
FROM OPENQUERY(LocalServerName, 'EXEC sp_who');

-- 2. 對臨時表進行後續查詢
SELECT * FROM #TmpWhere WHERE Status = 'runnable';

-- 3. 使用完畢清理
DROP TABLE #TmpWho;

關鍵點解析

進階:參數化調用(動態 SQL 構建)

DECLARE @SPName SYSNAME = 'sp_who2',
        @Param  VARCHAR(100) = 'active',
        @SQL    NVARCHAR(MAX),
        @Linked SYSNAME = @@SERVERNAME;

SET @SQL = 'SELECT * INTO #TmpResult FROM OPENQUERY(' + QUOTENAME(@Linked) + ', ''EXEC ' + QUOTENAME(@SPName) + ' ' + @Param + ''')';

EXEC sp_executesql @SQL;

SELECT * FROM #TmpResult;
DROP TABLE #TmpResult;
注意:動態 SQL 中單引號轉義(雙單引號),QUOTENAME 防止注入與標識符分隔問題。

替代方案對比

要點說明
環回鏈接服務器LocalServerName 為 @@SERVERNAME 返回的本地實例名,或手動創建指向自身的鏈接服務器。
OPENQUERY 要求目標服務器必須啟用 Data Access = True,且查詢字符串為常量/變量(不支持動態拼接的 EXEC)。
結果集元數據SELECT INTO 根據首個結果集列定義創建臨時表結構,存儲過程若有多結果集僅取第一個。
權限調用者需有存儲過程 EXECUTE 權限及 CREATE TABLE 權限(tempdb)。

總結

SELECT * INTO #Temp FROM OPENQUERY(Server, 'EXEC sp_Name') 是 SQL Server 2000/2005/2008 時代將存儲過程結果集物化的經典模式。現代版本(2012+)優先使用 WITH RESULT SETS 定義強類型結果集,配合 INSERT INTO #Temp EXEC... 簡潔高效。遺留系統維護時,確保本地鏈接服務器 Data Access = True 即可復現該模式。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
方案適用版本優點缺點
INSERT INTO #Temp EXEC sp_NameSQL Server 2000+語法直觀、支持多結果集舊版本不支持嵌套 INSERT、不可在函數中用
OPENQUERY + EXECSQL Server 2000+ (需 Data Access)繞過嵌套限制、可作為衍生表直接 JOIN需鏈接服務器配置、單引號轉義易錯
INSERT INTO #Temp EXEC('EXEC sp_Name')SQL Server 2005+無需鏈接服務器、動態構建易舊版本不支持
WITH RESULT SETS (SQL 2012+)SQL Server 2012+定義結果集元數據、強類型、無需臨時表預建需預知列結構、版本要求高