決定性與非決定性函數
假設資料庫狀態相同,任何時候以特定的輸入值集來呼叫具決定性函數時,一律會傳回相同的結果。即使所存取的資料庫維持在相同的狀態,每次以特定的輸入值集來呼叫非決定性函數時,都會傳回不同的結果。
無論是透過呼叫函數之計算資料行上的索引,還是透過參考函數的索引檢視,使用者自訂函數都有幾項屬性可決定 SQL Server Database Engine 為函數的結果編製索引的能力。函數的決定論 (Determinism) 是這類屬性的一種。例如,如果檢視參考任何不具決定性的函數,則無法在檢視上建立叢集索引。如需有關函數屬性 (包括決定性) 的詳細資訊,請參閱<使用者定義函數設計指導方針>。
此主題會識別內建系統函數的決定性,以及當使用者自訂函數的具決定性屬性包含擴充預存程序的呼叫時,所造成的影響。
內建函數決定論
您無法影響任何內建函數的決定論。每個內建函數屬於具決定性或不具決定性,主要取決於 SQL Server 實作函數的方式。
所有彙總和字串內建函數都是具決定性函數。如需這些函數的清單,請參閱<彙總函式 (Transact-SQL)>和<字串函數 (Transact-SQL)>。
下列內建函數 (來自彙總和字串函數以外的內建函數類別) 一定是具決定性函數。
ABS |
DATEDIFF |
POWER |
ACOS |
DAY |
RADIANS |
ASIN |
DEGREES |
ROUND |
ATAN |
EXP |
SIGN |
ATN2 |
FLOOR |
SIN |
CEILING |
ISNULL |
SQUARE |
COALESCE |
ISNUMERIC |
SQRT |
COS |
LOG |
TAN |
COT |
LOG10 |
YEAR |
DATALENGTH |
MONTH |
|
DATEADD |
NULLIF |
|
下列函數不一定是具決定性函數,但若是以決定性的方式來指定,則可用於索引檢視表或計算資料行的索引。
函數 |
註解 |
---|---|
CAST |
除非搭配 datetime、smalldatetime 或 sql_variant 使用,否則為決定性函數。 |
CONVERT |
除非存在這些條件之一,否則為具決定性函數:
|
CHECKSUM |
具決定性,但 CHECKSUM(*) 除外。 |
ISDATE |
若與 CONVERT 函數一併使用,只有在指定 CONVERT 樣式參數,且樣式不等於 0、100、9 或 109 時,才是具決定性的。 |
RAND |
RAND 只有在指定 seed 參數時才是具決定性的。 |
所有的組態、資料指標、中繼資料、安全性及系統統計函數都是不具決定性的。如需這些函數的清單,請參閱<組態函數 (Transact-SQL)>、<資料指標函數 (Transact-SQL)>、<中繼資料函數 (Transact-SQL)>、<安全性函數 (Transact-SQL)>和<系統統計函數 (Transact-SQL)>。
下列內建函數 (來自其他類別) 一定是不具決定性函數。
@@CONNECTIONS |
@@TOTAL_WRITE |
@@CPU_BUSY |
CURRENT_TIMESTAMP |
@@DBTS |
GETDATE |
@@IDLE |
GETUTCDATE |
@@IO_BUSY |
GET_TRANSMISSION_STATUS |
@@MAX_CONNECTIONS |
MIN_ACTIVE_ROWVERSION |
@@PACK_RECEIVED |
NEWID |
@@PACK_SENT |
NEWSEQUENTIALID |
@@PACKET_ERRORS |
PARSENAME |
@@TIMETICKS |
RAND |
@@TOTAL_ERRORS |
TEXTPTR |
@@TOTAL_READ |
從函數呼叫擴充預存程序
呼叫擴充預存程序的函數是不具決定性的,因為擴充預存程序可能對資料庫造成副作用。副作用是變更資料庫的全域狀態 (例如更新資料表),或變更檔案或網路這類外部資源 (例如修改檔案或傳送電子郵件訊息)。從使用者自訂函數執行擴充預存程序時不應該依靠傳回一致的結果集。不建議您使用會對資料庫造成副作用的使用者自訂函數。
從函數內部呼叫時,擴充預存程序無法傳回結果集給用戶端。傳回結果集給用戶端的任何開放式資料服務 (Open Data Services) API 都會收到 FAIL 的傳回碼。
擴充預存程序不得連回 SQL Server。而且,程序都無法加入相同的交易成為呼叫擴充預存程序的原始函數。
類似從批次或預存程序的引動過程,擴充預存程序是在執行 SQL Server 的 Microsoft Windows 安全帳戶內容中執行。擴充預存程序的擁有者在授權讓其他使用者可以執行該程序時應該考慮到這一點。