有效位數、小數位數與長度 (Transact-SQL)
適用於:Microsoft Fabric Microsoft網狀架構倉儲中的 SQL Server Azure SQL 資料庫 Azure SQL 受控執行個體 Azure Synapse Analytics Platform System (PDW) SQL 分析端點
位數 (Precision) 是指數字中總共的位數。 小數位數 (Scale) 則是指數字中小數點右方的位數。 例如,數位 123.45
的精確度 5
為 和 小數字數 2
。
在 SQL Server 中,numeric 和 decimal 資料類型的預設最大有效位數為 38。
數值資料類型的長度是用來儲存數字的位元組數目。 對於 varchar 和 char,字元字串的長度是位元陣數目。 對於 nvarchar 和 nchar,字元字串的長度是位元組配對的數目。 binary、varbinary 及 image 資料類型的長度為位元組的數目。 例如,int 資料類型可以保留 10 位數,儲存在 4 個位元組中且不接受小數點。 int 資料類型的有效位數是 10,長度是 4,小數位數是 0。
當您串連兩個 char、 varchar、 binary 或 varbinary 表達式時,產生的表達式長度是兩個來源運算式長度的總和,最多 8,000 個字節。
當您串連兩個 nchar 或 nvarchar 運算式時,產生的運算式長度是兩個來源表示式長度的總和,最多 4,000 個字節組。
當您比較相同數據類型的兩個表達式,但使用
UNION
、EXCEPT
或INTERSECT
來比較不同長度時,產生的長度是兩個表達式的較長時間。
備註
decimal 兩旁數值資料類型的有效位數和小數位數是固定的。 當算術運算子有兩個相同類型的運算式時,結果會有相同的資料類型,並具有定義給這個類型的有效位數和小數位數。 如果運算子有兩個含不同數值資料類型的運算式,資料類型優先順序的規則會定義這個結果的資料類型。 結果會有定義給它的資料類型的有效位數和小數位數。
下表定義在運算結果是 decimal 類型時,如何計算結果的有效位數和小數位數。 若符合下列其中一項條件,結果為 decimal:
- 兩個運算式都是 decimal。
- 一個運算式為 decimal,另一個運算式為優先順序低於 decimal 的資料類型。
操作數表達式會表示為表達式e1
,其有效位數和小s1
數字數為 ,而表示式e2
則以有效p1
位數p2
和小數位數s2
表示。 任何不是 十進位表達式的有效位數和小數字數 ,都是針對表達式數據類型所定義的有效位數和小數字數。 函式max(a, b)
表示要接受 或b
的較大值a
。 同樣地,min(a, b)
表示接受 或b
的較小值a
。
作業 | 結果有效位數 | 結果小數字數 1 |
---|---|---|
e1 + e2 | max(s1, s2) + max(p1 - s1, p2 - s2) + 1 | max(s1, s2) |
e1 - e2 | max(s1, s2) + max(p1 - s1, p2 - s2) + 1 | max(s1, s2) |
e1 * e2 | p1 + p2 + 1 | s1 + s2 |
e1 / e2 | p1 - s1 + s2 + max(6, s1 + p2 + 1) | max(6, s1 + p2 + 1) |
e1 { UNION | EXCEPT | INTERSECT } e2 | max(s1, s2) + max(p1 - s1, p2 - s2) | max(s1, s2) |
e1 % e2 | min(p1 - s1, p2 - s2) + max(s1, s2) | max(s1, s2) |
1 結果有效位數和小數位數的絕對最大值為38。 當結果有效位數大於 38 時,會縮小至 38,並會縮減對應的小數位數,以防止截斷結果的整數部分。 在某些情況下,例如乘法或除法,則不會減少小數字數係數,以維持小數精確度,不過可以引發溢位錯誤。
除了減法運算之外,我們需要 max(p1 - s1, p2 - s2)
places 來儲存十進位數的整數部分。 如果沒有足夠的空間來儲存它們(也就是 max(p1 - s1, p2 - s2) < min(38, precision) - scale
),則小數字數會減少,以提供足夠的空間給整數部分。 產生的小數字數為 min(precision, 38) - max(p1 - s1, p2 - s2)
,因此小數部分可能會四捨五入以符合產生的小數字數。
在乘法及除法運算中,我們需要 precision - scale
位置來儲存結果的整數部分。 可能會使用下列規則來縮小小數位數:
- 若整數部分小於 32,則結果的小數位數會縮減至
min(scale, 38 - (precision-scale))
,因為它不可大於38 - (precision-scale)
。 在此情況下,結果可能會四捨五入。 - 如果小數字數小於 6,且整數部分大於 32,則不會變更。 在此情況下,如果無法放入 十進位數(38, 小數字數),可能會引發溢位錯誤。
- 如果小數字數大於 6,而且整數部分大於 32,則小數位數會設定為 6。 在此情況下,整數部分和小數字數都會減少,產生的類型為decimal(38,6)。 如果整數部分無法放入 32 位數,則結果可能會四捨五入為 7 個小數位數,或擲回溢位錯誤。
範例
下列表達式會傳回沒有四捨五入的結果 0.00000090000000000
,因為結果可以放入 decimal(38, 17):
SELECT CAST(0.0000009000 AS DECIMAL(30, 20)) * CAST(1.0000000000 AS DECIMAL(30, 20)) [decimal(38, 17)];
在這裡情況下,有效位數為 61
,而小數字數為 40
。
整數部分 (precision-scale = 21)
小於 32,因此此案例是乘法規則中的第一個案例,而小數字數會計算為 min(scale, 38 - (precision-scale)) = min(40, 38 - (61-40)) = 17
。 結果類型為 decimal(38, 17)。
下列表達式會傳回符合 decimal(38, 6)的結果0.000001
:
SELECT CAST(0.0000009000 AS DECIMAL(30, 10)) * CAST(1.0000000000 AS DECIMAL(30, 10)) [decimal(38, 6)];
在這裡情況下,有效位數為 61
,而小數字數為 20
。
小數字數大於 6,整數部分 (precision-scale = 41
) 大於 32。 此案例是乘法規則中的第三個案例,結果類型為 decimal(38, 6) 。