共用方式為


程式設計資料庫引擎擴充儲存程序

適用於:SQL Server

這很重要

SQL Server 的未來版本將移除此功能。 請避免在新的開發工作中使用此功能,並計劃修改目前使用此功能的應用程式。 改用 CLR 整合

擴充儲存程序的運作方式

擴充儲存程序運作的過程如下:

  1. 當用戶端執行擴充儲存程序時,請求會以表格資料串流(TDS)或簡易物件存取協定(SOAP)格式從用戶端應用程式傳送至 SQL Server。

  2. SQL Server 會搜尋與擴充儲存程序相關的 DLL,如果還沒載入該 DLL,就會載入。

  3. SQL Server 呼叫所請求的擴充儲存程序(以 DLL 內部函式實作)。

  4. 擴充儲存程序透過擴充儲存程序 API 將結果集與參數回傳給伺服器。

過去,開放資料服務(Open Data Services)被用來撰寫伺服器應用程式,例如通往非 SQL Server 資料庫環境的閘道器。 SQL Server 不支援開放資料服務 API 中已過時的部分。 原始開放資料服務 API 中唯一仍被 SQL Server 支援的是擴充的儲存程序函式,因此該 API 被重新命名為擴展儲存程序 API。

隨著分散式查詢與 CLR 整合的興起,對擴充儲存程序 API 應用程式的需求已大幅取代。

如果你已有閘道應用程式,就不能用 SQL Server 附帶的那個 opends60.dll 來執行應用程式。 Gateway 應用程式已不再支援。

擴充儲存程序與 CLR 整合的比較

CLR 整合提供了比起在 Transact-SQL 中難以表達或無法撰寫的伺服器端邏輯更穩健的替代方案。 在早期版本的 SQL Server 中,擴充儲存程序(XPs)是資料庫應用程式開發者撰寫此類程式碼的唯一機制。

透過 CLR 整合,過去以儲存程序形式撰寫的邏輯,通常更適合以表值函式表示,讓函式所產生的結果能 SELECT 透過將函式嵌入 FROM 子句中來查詢。

欲了解更多資訊,請參閱 CLR 整合概述

擴充儲存程序的執行特性

擴充儲存程序的執行具有以下特性:

  • 擴充的儲存程序函式是在 SQL Server 的安全上下文下執行。

  • 擴充的儲存程序函式在 SQL Server 的程序空間中執行。

  • 執行擴充儲存程序的執行緒與用戶端連線所使用的執行緒相同。

這很重要

在為伺服器新增擴充儲存程序並授予其他使用者執行權限之前,系統管理員應徹底審查每個擴充儲存程序,確保其不含有害或惡意程式碼。

在擴充儲存程序 DLL 載入後,DLL 會持續載入在伺服器的位址空間中,直到 SQL Server 停止運作或管理員明確以 。DBCC <DLL_name> (FREE)

擴充儲存程序可從 Transact-SQL 作為儲存程序執行,使用 EXECUTE 以下語句:

EXECUTE @retval = xp_extendedProcName @param1, @param2 OUTPUT;

參數

@ 雷特瓦爾

一個回報價值。

@ 段落1

一個輸入參數。

@ Param2

輸入/輸出參數。

謹慎

擴充儲存程序提供效能提升及 SQL Server 功能擴充。 然而,由於擴充的儲存程序 DLL 與 SQL Server 共用相同位址空間,問題程序可能會對 SQL Server 的運作產生負面影響。 雖然擴充儲存程序 DLL 拋出的例外由 SQL Server 處理,但仍可能損害 SQL Server 的資料區域。 作為安全預防措施,只有 SQL Server 系統管理員能為 SQL Server 新增擴充的儲存程序。 這些程序在安裝前應進行徹底測試。

將結果集傳送到使用擴充儲存程序 API 的伺服器

當將結果集傳送到 SQL Server,擴充儲存程序應呼叫相應的 API: 如下:

  • srv_sendmsg該函數可在所有列srv_sendrow(若有)為 之前或之後,任意順序被呼叫。 所有訊息必須先發送給用戶端,才能以 發送完成狀態 srv_senddone

  • 每傳送給客戶端的一列,該 srv_sendrow 函式會被呼叫一次。 所有列必須先傳送給用戶端,然後才會傳送任何訊息、狀態值或完成狀態,且參數 srv_sendmsgsrv_statussrv_pfield,或 srv_senddone

  • 傳送一列未定義 srv_describe 所有欄位的列,會導致應用程式發出資訊錯誤訊息並返回 FAIL 用戶端。 在這種情況下,該列並未被發送。

建立擴充的儲存程序

擴充的儲存程序是一個帶有原型的 C/C++ 函式:

SRVRETCODE xp_extendedProcName (SRVPROC *);

使用前綴 xp_ 是可選的。 擴充儲存程序名稱在 Transact-SQL 語句中引用時會區分大小寫,無論伺服器上安裝的代碼頁/排序順序為何。 當你建立 DLL(雙重學習環境)時:

  • 如果需要進入點,則寫一個 DllMain 函式。

    此功能是可選的。 如果你沒有在原始碼中提供,編譯器會連結自己的版本,而這個版本只會回傳 TRUE。 如果你提供函 DllMain 式,作業系統會在執行緒或程序連接或分離 DLL 時呼叫該函式。

  • 所有從 DLL 外部呼叫的函式(所有擴充儲存程序 Efunctions)都必須匯出。

    你可以在檔案區.def塊中列出函式名稱EXPORTS,或在原始碼前加上 __declspec(dllexport),一個 Microsoft 編譯器副檔名(__declspec()以兩個底線開頭)。

這些檔案是建立擴充儲存程序 DLL 所必需的。

檔案 Description
srv.h 擴充儲存程序 API 標頭檔案
opends60.lib 匯入函式庫 opends60.dll

若要建立擴充的儲存程序 DLL,請建立一個類型為 Dynamic Link Library 的專案。 欲了解更多關於建立 DLL 的資訊,請參閱開發環境文件。

所有擴充的儲存程序 DLL 都應實作並匯出以下函式:

__declspec(dllexport) ULONG __GetXpVersion()
{
   return ODS_VERSION;
}

__declspec(dllexport) 是 Microsoft 專屬的編譯器擴充套件。 如果你的編譯器不支援這個指令,你應該在檔案中匯出這個函式 DEF ,放在該 EXPORTS 區段下。

當 SQL Server 以追蹤標誌 -T260 啟動,或有擁有系統管理員權限的使用者執行 DBCC TRACEON (260),且擴充儲存程序 DLL 不支援 __GetXpVersion()時,錯誤日誌會印出以下警告訊息(__GetXpVersion() 以兩個底線開頭)。

Error 8131: Extended stored procedure DLL '%' does not export __GetXpVersion().

若擴充儲存程序 DLL 匯出 __GetXpVersion(),但函式回傳的版本低於伺服器所需版本,則錯誤日誌會印出警告訊息,說明函式回傳的版本與伺服器預期的版本。 如果你收到這個訊息,代表你從 回傳了一個錯誤的值 __GetXpVersion(),或者你正在用較舊版本 srv.h的 編譯。

備註

SetErrorMode,Win32 函式,不應該在擴充儲存程序中被呼叫。

長期執行的擴充儲存程序應定期呼叫 srv_got_attention ,這樣當連線被終止或批次中止時,程序可以自行終止。

若要除錯擴充的儲存程序 DLL,請將其複製到 SQL Server \Binn 目錄。 若要指定除錯會話的執行檔,請輸入 SQL Server 可執行檔的路徑與檔名(例如, C:\Program Files\Microsoft SQL Server\MSSQL16.MSSQLSERVER\MSSQL\Binn\sqlservr.exe。 關於參數的資訊 sqlservr ,請參見 sqlservr 應用程式

在 SQL Server 中新增擴充的儲存程序

包含擴充儲存程序函式的 DLL 作為 SQL Server 的擴充。 安裝 DLL 時,將檔案複製到目錄,例如預設包含標準 SQL Server DLL 檔案C:\Program Files\Microsoft SQL Server\MSSQL16.0.<x>\MSSQL\Binn 的目錄。

在擴充儲存程序 DLL 複製到伺服器後,SQL Server 系統管理員必須將 DLL 中的每個擴充儲存程序函式註冊到 SQL Server。 這是透過 sp_addextendedproc 系統儲存程序來完成的。

這很重要

系統管理員應徹底審查擴充儲存程序,確保其不含有害或惡意程式碼,然後才加入伺服器並授權其他使用者執行權限。 驗證所有使用者輸入。 在驗證使用者輸入前,不要把它串接在一起。 請勿執行由未經驗證之使用者輸入所建構的命令。

第一個參數 表示 sp_addextendedproc 函式名稱,第二個參數指定該函式所在的 DLL 名稱。 你應該指定 DLL 的完整路徑。

備註

未註冊完整路徑的現有 DLL 在升級到 SQL Server 2005(9.x)或更新版本後就無法使用。 要解決這個問題,請先 sp_dropextendedproc 取消註冊 DLL,然後重新註冊並指定 sp_addextendedproc, 完整路徑。

在 中 sp_addextendedproc 指定的函數名稱必須與 DLL 中函數的名稱完全相同,包括情況。 例如,此指令將位於名為 xp_hello.dll的 dll 中的函xp_hello,式註冊為 SQL Server 擴充儲存程序:

sp_addextendedproc 'xp_hello', 'c:\Program Files\Microsoft SQL Server\MSSQL13.0.MSSQLSERVER\MSSQL\Binn\xp_hello.dll';

如果 DLL sp_addextendedproc 中指定的函式名稱與函式名稱不完全一致,新名稱會註冊在 SQL Server,但該名稱無法使用。 例如,雖然 xp_Hello 註冊為位於 xp_hello.dll的 SQL Server 擴充儲存程序,但如果你之後再呼叫 xp_Hello 該函式,SQL Server 找不到 DLL 中的函式。

-- Register the function (xp_hello) with an initial upper case
sp_addextendedproc 'xp_Hello', 'c:\xp_hello.dll';

-- Use the newly registered name to call the function
DECLARE @txt VARCHAR(33);
EXEC xp_Hello @txt OUTPUT;

以下是錯誤訊息:

Server: Msg 17750, Level 16, State 1, Procedure xp_Hello, Line 1
Could not load the DLL xp_hello.dll, or one of the DLLs it references. Reason: 127(The specified procedure could not be found.).

如果 中 sp_addextendedproc 指定的函式名稱與 DLL 中的函式名稱完全一致,且 SQL Server 實例的排序不區分大小寫,使用者即可使用名稱中任意大小寫字母組合呼叫擴充儲存程序。

-- Register the function (xp_hello)
sp_addextendedproc 'xp_hello', 'c:\xp_hello.dll';

-- The following example succeeds in calling xp_hello
DECLARE @txt VARCHAR(33);
EXEC xp_Hello @txt OUTPUT;

DECLARE @txt VARCHAR(33);
EXEC xp_HelLO @txt OUTPUT;

DECLARE @txt VARCHAR(33);
EXEC xp_HELLO @txt OUTPUT;

當 SQL Server 實例的排序是大小寫區分時,若程序是以不同案例呼叫,SQL Server 無法呼叫該擴充儲存程序。 即使它註冊的名稱和排序方式與 DLL 中的函式完全相同,這點依然成立。

-- Register the function (xp_hello)
sp_addextendedproc 'xp_hello', 'c:\xp_hello.dll';

-- The following example results in an error
DECLARE @txt VARCHAR(33);
EXEC xp_HELLO @txt OUTPUT;

以下是錯誤訊息:

Server: Msg 2812, Level 16, State 62, Line 1

你不需要停止再重啟 SQL Server。

查詢安裝於 SQL Server 的擴充儲存程序

經過 SQL Server 認證的使用者可透過執行 sp_helpextendedproc 系統程序顯示目前定義的擴充儲存程序及每個 DLL 所屬的 DLL 名稱。 例如,以下範例回傳屬於的 DLL xp_hello

sp_helpextendedproc 'xp_hello';

sp_helpextendedproc 執行時未指定擴充儲存程序,則所有擴充儲存程序及其 DLL 都會顯示。

從 SQL Server 移除擴充儲存程序

要將每個擴充儲存程序函式丟棄到使用者定義的擴充儲存程序 DLL,SQL Server 系統管理員必須執行該 sp_dropextendedproc 系統儲存程序,並指定函式名稱及該函式所在的 DLL 名稱。 例如,此指令移除位於 SQL Server 中名為 xp_hello.dll, DLL 的函式 xp_hello

sp_dropextendedproc 'xp_hello';

sp_dropextendedproc 不會丟棄系統擴充的儲存程序。 相反地,系統管理員應該拒絕 EXECUTE 將擴展儲存程序授權給 公開 角色。

卸載擴充儲存程序 DLL

SQL Server 在呼叫 DLL 函式時,立即載入擴充的儲存程序 DLL。 DLL 會一直載入,直到伺服器關閉或系統管理員使用 DBCC 該語句卸載它為止。 例如,此指令會卸載 , xp_hello.dll允許系統管理員將該檔案的新版本複製到目錄,而不必關閉伺服器:

DBCC xp_hello(FREE);