有效位數、小數位數與長度 (Transact-SQL)
適用於:sql Server
Azure SQL 資料庫 Azure SQL 受控執行個體
Azure Synapse Analytics Analytics
Platform System (PDW)
SQL 分析端點在 Microsoft Fabric SQL 資料庫中Microsoft
網狀
架構倉儲中的 SQL 分析端點Microsoft網狀架構
位數 (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) 。