決定性與非決定性函數

更新: 2006 年 7 月 17 日

假設資料庫狀態相同,任何時候以特定的輸入值集來呼叫決定性函數時,一律會傳回相同的結果。即使所存取的資料庫維持在相同的狀態,每次以特定的輸入值集來呼叫非決定性函數時,都會傳回不同的結果。

無論是透過呼叫函數之計算資料行上的索引,還是透過參考函數的索引檢視,使用者自訂函數都有幾項屬性可決定 SQL Server Database Engine 為函數的結果編製索引的能力。函數的決定論 (Determinism) 是這類屬性的一種。例如,如果檢視參考任何不具決定性的函數,則無法在檢視上建立叢集索引。如需有關函數屬性 (包括決定性) 的詳細資訊,請參閱<使用者自訂函數設計指導方針>。

此主題會識別內建系統函數的決定性,以及當使用者自訂函數的具決定性屬性包含擴充預存程序的呼叫時,所造成的影響。

內建函數決定論

您無法影響任何內建函數的決定論。每個內建函數屬於具決定性或不具決定性,主要取決於 Microsoft SQL Server 2005 實作函數的方式。

所有彙總和字串內建函數都是具決定性函數。如需這些函數的清單,請參閱<彙總函數 (Transact-SQL)>和<字串函數 (Transact-SQL)>。

下列的內建函數不屬於彙總函數和字串函數,一律會視為具決定性函數。

ABS

DATEDIFF

PARSENAME

ACOS

DAY

POWER

ASIN

DEGREES

RADIANS

ATAN

EXP

ROUND

ATN2

FLOOR

SIGN

CEILING

ISNULL

SIN

COALESCE

ISNUMERIC

SQUARE

COS

LOG

SQRT

COT

LOG10

TAN

DATALENGTH

MONTH

YEAR

DATEADD

NULLIF

 

下列函數並非永遠是具決定性函數,但若是以決定性的方式來指定,則可用於索引檢視或計算資料行的索引。

函數 註解

CAST

除非搭配 datetimesmalldatetimesql_variant 使用,否則為決定性函數。

CONVERT

除非存在這些條件之一,否則為具決定性函數:

  • 來源類型為 sql_variant
  • 目標類型為 sql_variant,且其來源類型為非決定性函數。
  • 來源或目標類型為 datetimesmalldatetime;其他來源或目標類型為字元字串,而且指定了非決定性的樣式。若要具有決定性,樣式參數必須是常數。另外,小於或等於 100 的樣式也是非決定性的,但不包括樣式 20 和 21。除了樣式 106、107、109 和 113 以外,大於 100 的樣式都具有決定性。

CHECKSUM

具決定性,但 CHECKSUM(*) 除外。

ISDATE

若與 CONVERT 函數一併使用,只有在指定 CONVERT 樣式參數,且樣式不等於 0、100、9 或 109 時,才是具決定性的。

RAND

RAND 只有在指定 seed 參數時才是具決定性的。

所有的組態、資料指標、中繼資料、安全性及系統統計函數都是不具決定性的。如需這些函數的清單,請參閱<組態函數 (Transact-SQL)>、<資料指標函數 (Transact-SQL)>、<中繼資料函數 (Transact-SQL)>、<安全性函數 (Transact-SQL)>和<系統統計函數 (Transact-SQL)>。

下列屬於其他類別的內建函數,一律是不具決定性的。

@@CONNECTIONS

@@TOTAL_READ

@@CPU_BUSY

@@TOTAL_WRITE

@@DBTS

CURRENT_TIMESTAMP

@@IDLE

GETDATE

@@IO_BUSY

GETUTCDATE

@@MAX_CONNECTIONS

GET_TRANSMISSION_STATUS

@@PACK_RECEIVED

MIN_ACTIVE_ROWVERSION

@@PACK_SENT

NEWID

@@PACKET_ERRORS

NEWSEQUENTIALID

@@TIMETICKS

RAND

@@TOTAL_ERRORS

TEXTPTR

從函數呼叫擴充預存程序

呼叫擴充預存程序的函數是不具決定性的,因為擴充預存程序可能對資料庫造成副作用。副作用是變更資料庫的全域狀態 (例如更新資料表),或變更檔案或網路這類外部資源 (例如修改檔案或傳送電子郵件訊息)。從使用者自訂函數執行擴充預存程序時不應該依靠傳回一致的結果集。不建議您使用會對資料庫造成副作用的使用者自訂函數。

從函數內部呼叫時,擴充預存程序無法傳回結果集給用戶端。傳回結果集給用戶端的任何開放式資料服務 (Open Data Services) API 都會收到 FAIL 的傳回碼。

擴充預存程序不得連回 SQL Server。而且,程序都無法加入相同的交易成為呼叫擴充預存程序的原始函數。

類似從批次或預存程序的引動過程,擴充預存程序是在執行 SQL Server 的 Microsoft Windows 安全帳戶內容中執行。擴充預存程序的擁有者在授權讓其他使用者可以執行該程序時應該考慮到這一點。

請參閱

概念

使用者自訂函數設計指導方針
資料表值使用者自訂函數
內嵌使用者自訂函數
將預存程序重寫為函數

其他資源

設計使用者自訂函數

說明及資訊

取得 SQL Server 2005 協助

變更歷程記錄

版本 歷程記錄
變更的內容:
  • 在 CONVERT 函數的描述中新增資訊以清楚說明:除非來源或目標類型為 datetimesmalldatetime;其他來源或目標類型為字元字串,而且指定了非決定性樣式,否則使用 CONVERT 就可以產生決定性的結果。
  • 同時也釐清哪些樣式具有決定性,而哪些不具決定性。