強制參數化

您可以藉由指定將資料庫中所有的 SELECT、INSERT、UPDATE 與 DELETE 陳述式依據特定的限制進行參數化,以覆寫 SQL Server 的預設簡易參數化行為。在 ALTER DATABASE 陳述式中將 PARAMETERIZATION 選項設為 FORCED,即可啟用強制參數化。強制參數化可藉由降低查詢編譯與重新編譯的頻率,來增進特定資料庫的效能。可經由強制參數化獲益的資料庫通常會有來自來源 (如銷售點應用程式) 的大量並行查詢。

當 PARAMETERIZATION 選項設為 FORCED 時,出現在 SELECT、INSERT、UPDATE 或 DELETE 陳述式中且以任何形式提交的常值,都會在查詢編譯期間轉換為參數。但出現於下列查詢結構中的常值則為例外:

  • INSERT...EXECUTE 陳述式。

  • 預存程序、觸發程序或使用者自訂函數主體中的陳述式。SQL Server 會重複使用這些常式的查詢計畫。

  • 已在用戶端應用程式上完成參數化的準備陳述式。

  • 含有 XQuery 方法呼叫的陳述式,其方法會出現在引數通常已參數化的內容中,如 WHERE 子句。若此方法出現在引數未參數化的內容中,則該陳述式的其他部分會進行參數化。

  • Transact-SQL 資料指標中的陳述式。(API 資料指標中的 SELECT 陳述式會進行參數化。)

  • 被取代的查詢結構。

  • 在 ANSI_PADDING 或 ANSI_NULLS 設為 OFF 之內容中執行的任何陳述式。

  • 包含超過 2,097 個可參數化之常值的陳述式。

  • 參考變數的陳述式,如 WHERE T.col2 >= @bb。

  • 含有 RECOMPILE 查詢提示的陳述式。

  • 含有 COMPUTE 子句的陳述式。

  • 包含 WHERE CURRENT OF 子句的陳述式。

另外,下列查詢子句不參數化。請注意,在這些案例中,只有子句不參數化。相同查詢內的其他子句可進行強制參數化。

  • 任何 SELECT 陳述式的 <select_list>。其中包括子查詢的 SELECT 清單,以及 INSERT 陳述式內的 SELECT 清單。

  • 出現在 IF 陳述式內的子查詢 SELECT 陳述式。

  • 查詢的 TOP、TABLESAMPLE、HAVING、GROUP BY、ORDER BY、OUTPUT...INTO 或 FOR XML 子句。

  • OPENROWSET、OPENQUERY、OPENDATASOURCE、OPENXML 或任何 FULLTEXT 運算子的引數 (直接做為引數或做為子運算式)。

  • LIKE 子句的 pattern 和 escape_character 引數。

  • CONVERT 子句的 style 引數。

  • IDENTITY 子句中的整數常數。

  • 使用 ODBC 延伸語法指定的常數。

  • 可摺疊常數的運算式,其為 +、-、*、/ 及 % 運算子的引數。在考量是否可進行強制參數化時,若符合下列其中一項條件,則 SQL Server 會認定運算式為可摺疊常數的:

    • 運算式中未出現資料行、變數或子查詢。

    • 運算式中含有 CASE 子句。

    如需可摺疊常數之運算式的詳細資訊,請參閱<低查詢效能的疑難排解:常數摺疊和基數估計期間的運算式評估>。

  • 查詢提示子句的引數。這些包括 FAST 查詢提示的 number_of_rows 引數、MAXDOP 查詢提示的 number_of_processors 引數,以及 MAXRECURSION 查詢提示的 number 引數。

參數化會發生於個別 Transact-SQL 陳述式層級上。換句話說,批次中的個別陳述式會進行參數化。編譯之後,參數化查詢會在最初提交查詢的批次內容中執行。若已快取查詢的執行計畫,即可藉由參考 sys.syscacheobjects 動態管理檢視的 sql 資料行,來判斷查詢是否已參數化。若查詢已參數化,則在此資料行中,參數的名稱與資料類型會顯示在提交批次的文字之前,如 (@1 tinyint)。如需查詢計畫快取的相關資訊,請參閱<執行計畫快取與重複使用>。

[!附註]

參數名稱可以是任意的名稱。使用者或應用程式不應依賴特定的命名順序。而且,在 SQL Server 版本和 Service Pack 升級版之間可變更下列各項:參數名稱、參數化的常值選項和參數化文字的間距。

參數的資料類型

當 SQL Server 將常值參數化時,參數會轉換為下列資料類型:

  • 將以其他方式調整大小以符合 int 資料類型的整數常值,參數化為 int。屬於含有任何比較運算子之述詞的較大整數常值 (包括 <、<=、=、!=、>、>=、!、<, !>、<>、ALL、ANY、SOME、BETWEEN 和 IN) 會參數化為 numeric(38,0)。不屬於含有比較運算子之述詞的較大常值,會參數化為 numeric,其有效位數夠大正好足以支援其大小,而其小數位數為 0。

  • 屬於含有比較運算子之述詞的固定點數值常值,會參數化為 numeric,其有效位數為 38,而其小數位數夠大正好足以支援其大小。不屬於含有比較運算子之述詞的固定點數值常值,會參數化為 numeric,其有效位數與小數位數夠大正好足以支援其大小。

  • 浮點數值常值會參數化為 float(53)。

  • 如果非 Unicode 字串常值可容納於 8,000 個字元中,即會參數化為 varchar(8000),如果該常值大於 8,000 個字元,則會參數化為 varchar(max)。

  • 如果 Unicode 字串常值可容納於 4,000 個 Unicode 字元中,即會參數化為 nvarchar(4000),如果該常值大於 4,000 個字元,則會參數化為 nvarchar(max)。

  • 如果二進位常值可容納於 8,000 個位元組中,就會參數化為 varbinary(8000)。如果該常值大於 8,000 個位元組,就會轉換為 varbinary(max)。

  • Money 類型常值會參數化為 money。

使用強制參數化的指導方針

將 PARAMETERIZATION 選項設為 FORCED 時,請考量下列事項:

  • 強制參數化一旦生效後,會在編譯查詢時將查詢中的常值 (常數) 變更為參數。因此,查詢最佳化工具可能會選擇到次佳的查詢計畫。特別是,查詢最佳化工具較不可能比對查詢與索引檢視或計算資料行上的索引。它也可會為資料分割資料表與分散式資料分割檢視上的查詢選擇次佳的計畫。針對非常依賴索引檢視或計算資料行上索引的環境,就不應該使用強制參數化。一般而言,應由具有經驗的資料庫管理員判斷 PARAMETERIZATION FORCED 選項的執行不會對效能造成不良影響後,才必須使用此選項。

  • 只要在查詢執行之內容所屬的資料庫中,將 PARAMETERIZATION 選項設為 FORCED,參考多個資料庫的分散式查詢即能使用強制參數化。

  • 將 PARAMETERIZATION 選項設為 FORCED,就會從資料庫的計畫快取中排清目前正在編譯、重新編譯或執行之計畫以外的所有查詢計畫。在設定變更期間編譯或執行的查詢計畫,會在下次執行查詢時進行參數化。

  • 設定 PARAMETERIZATION 選項是不需要資料庫層級獨佔鎖定的線上作業。

  • 當 SQL Server 資料庫的相容性設為 80,或將舊版執行個體上的資料庫附加到 SQL Server 2005 或更新版本的執行個體時,就會停用強制參數化 (設為 SIMPLE)。

  • 在重新附加或還原資料庫時,會保留目前 PARAMETERIZATION 選項的設定。

您可以指定在單一查詢以及語法上相同但只有其參數值不同的查詢嘗試簡單參數化,以覆寫強制參數化的行為。反之,您可以指定只在一組語法相同的查詢嘗試強制參數化,即使資料庫中已停用強制參數化。此即為計畫指導的用途。如需詳細資訊,請參閱<使用計畫指南指定查詢參數化行為>。

[!附註]

當 PARAMETERIZATION 選項設定成 FORCED 時,錯誤訊息的報告可能會與簡單參數化的報告不同:當簡單參數化之下報告的訊息較少時,可報告多個錯誤訊息,而且發生錯誤的行號報告可能會不正確。