有效位數、小數位數與長度 (Transact-SQL)

適用於:Microsoft Fabric 中 Microsoft Fabric倉儲中的 SQL ServerAzure SQL 資料庫 Azure SQL 受控執行個體 Azure SynapseAnalytics Analytics Platform System (PDW)SQL 分析端點

位數 (Precision) 是指數字中總共的位數。 小數位數 (Scale) 則是指數字中小數點右方的位數。 例如,數位 123.45 的精確度 5 為 和 小數字數 2

在 SQL Server 中,numericdecimal 資料類型的預設最大有效位數為 38。

數值資料類型的長度是用來儲存數字的位元組數目。 對於 varcharchar,字元字串的長度是位元陣數目。 對於 nvarchar 和 nchar,字元字串的長度是位元組配對的數目。 binaryvarbinaryimage 資料類型的長度為位元組的數目。 例如,int 資料類型可以保留 10 位數,儲存在 4 個位元組中且不接受小數點。 int 資料類型的有效位數是 10,長度是 4,小數位數是 0。

  • 當您串連兩個 charvarcharbinaryvarbinary 表達式時,產生的表達式長度是兩個來源運算式長度的總和,最多 8,000 個字節。

  • 當您串連兩個 nchar 或 nvarchar 運算式時,產生的運算式長度是兩個來源表示式長度的總和,最多 4,000 個字節組。

  • 當您比較相同數據類型的兩個表達式,但使用 UNIONEXCEPTINTERSECT來比較不同長度時,產生的長度是兩個表達式的較長時間。

備註

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 位置來儲存結果的整數部分。 可能會使用下列規則來縮小小數位數:

  1. 若整數部分小於 32,則結果的小數位數會縮減至 min(scale, 38 - (precision-scale)),因為它不可大於 38 - (precision-scale)。 在此情況下,結果可能會四捨五入。
  2. 如果小數字數小於 6,且整數部分大於 32,則不會變更。 在此情況下,如果無法放入 十進位數(38, 數字數),可能會引發溢位錯誤。
  3. 如果小數字數大於 6,而且整數部分大於 32,則小數位數會設定為 6。 在此情況下,整數部分和小數字數都會減少,產生的類型為decimal(38,6)。 如果整數部分無法放入 32 位數,則結果可能會四捨五入為 6 個小數位數,或擲回溢位錯誤。

範例

下列表達式會傳回沒有四捨五入的結果 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)

另請參閱