SQL Server の有効桁数 (precision) と 小数点以下桁数 (scale) について
有効桁数 (precision) と 小数点以下桁数 (scale)
DECIMAL を使った計算列を作った時などに、有効桁数 (precision) と 小数点以下桁数 (scale) がなぜそれになったのかな、と思ったことはありませんか?
SQL Server では、DECIMAL の値の計算の結果がどのような有効桁数と小数点以下桁数になるかのルールがあります。
この記事では、SQL Server の有効桁数と小数点以下桁数についてと、DECIMAL の計算結果の有効桁数と小数点以下桁数のルールについてご説明します。
有効桁数 (precision) と 小数点以下桁数 (scale) とは?
有効桁数 (precision) と 小数点以下桁数 (scale) とは、数字の次の箇所の桁数を指します。
- 有効桁数 (precision) - 数字の部分全体の桁数
- 小数点以下桁数 (scale) - 小数点より右側の桁数
例えば、12345.678 という数字があった場合、有効桁数は 8、小数点以下桁数は 3 になります。
DECIMAL 型の値を定義する時は DECIMAL(precision, scale) のように定義します。
ですので、例えば DECIMAL(8, 2) のように定義した場合は、123456.78 のように全体が 8 桁で小数点以下が 2 桁になります。
DECIMAL のデフォルトの有効桁数は 18 で、デフォルトの小数点以下桁数は 0 です。
DECIMAL のデフォルトの有効桁数の最大値は 38 で、有効桁数 に 38 より大きい数字を指定しようとするとエラーになります。
INT の有効桁数は 10 で、小数点以下桁数は 0 ということになります。
DECIMAL の計算結果のデータ型のルール
SQL Server で、DECIMAL 以外の数値データ型の場合は、同じデータ型同士で演算しても有効桁数と小数点以下桁数は変わりません。
違う数値データ型の演算をした場合は、データ型の優先順位の高い方に合わせて計算されます。
DECIMAL データ型同士で演算する時や、DECIMAL 型に暗黙的に変換されて演算が行われる時には、計算結果の有効桁数と小数点以下桁数が変わります。
和・差・積・商の有効桁数と小数点以下桁数のルール
DECIMAL の和・差・積・商の計算結果の有効桁数と小数点以下桁数は次のようになります。
演算 | 結果の有効桁数 | 結果の小数点以下桁数 |
---|---|---|
DECIMAL(p1, s1) + DECIMAL(p2, s2) | max(s1, s2) + max(p1 - s1, p2 - s2) + 1 | max(s1, s2) |
DECIMAL(p1, s1) - DECIMAL(p2, s2) | max(s1, s2) + max(p1 - s1, p2 - s2) + 1 | max(s1, s2) |
DECIMAL(p1, s1) * DECIMAL(p2, s2) | p1 + p2 + 1 | s1 + s2 |
DECIMAL(p1, s1) / DECIMAL(p2, s2) | p1 - s1 + s2 + max(6, s1 + p2 + 1) | max(6, s1 + p2 + 1) |
max(値1、 値2) のようになっている箇所は、大き方の値を使うという意味です。
それぞれ、実際に確認してみましょう。
足し算の計算結果の有効桁数と小数点以下桁数
一つ目の SELECT 文では、DECIMAL(19, 2) の変数 @Value1 と、DECIMAL(10, 4) の変数 @Value2 を足し算した結果のデータ型の有効桁数と小数点以下桁数を、SQL_VARIANT_PROPERTY 関数を使って確認しています。
二つ目の SELECT 文では、ルールに従って、元のデータ型の有効桁数と小数点以下桁数から、結果の有効桁数と小数点以下桁数を計算してみています。
演算 | 結果の有効桁数 | 結果の小数点以下桁数 |
---|---|---|
DECIMAL(p1, s1) + DECIMAL(p2, s2) | max(s1, s2) + max(p1 - s1, p2 - s2) + 1 | max(s1, s2) |
大きいほうの値を取得するのに GREATEST 関数を使っています。
DECLARE @Value1 DECIMAL(19, 2) = 111.11, @Value2 DECIMAL(10, 4) = 222.22; SELECT @Value1 AS Value1, @Value2 AS Value2, @Value1 + @Value2 AS Result, SQL_VARIANT_PROPERTY(@Value1 + @Value2, 'BaseType') AS [BaseType], SQL_VARIANT_PROPERTY(@Value1 + @Value2, 'Precision') AS [Precision], SQL_VARIANT_PROPERTY(@Value1 + @Value2, 'Scale') AS [Scale]; SELECT GREATEST(2, 4) + GREATEST(19 - 2, 10 - 4) + 1 AS ResultPrecision, GREATEST(2, 4) AS ResultScale;
ルール通りに計算結果の有効桁数が 22 と小数点以下桁数が 4 で、DECIMAL(22, 4) になってますね。
引き算の計算結果の有効桁数と小数点以下桁数
先ほどと同様の条件で、引き算した結果のデータ型の有効桁数と小数点以下桁数を確認してみます。
演算 | 結果の有効桁数 | 結果の小数点以下桁数 |
---|---|---|
DECIMAL(p1, s1) - DECIMAL(p2, s2) | max(s1, s2) + max(p1 - s1, p2 - s2) + 1 | max(s1, s2) |
DECLARE @Value1 DECIMAL(19, 2) = 111.11, @Value2 DECIMAL(10, 4) = 222.22; SELECT @Value1 AS Value1, @Value2 AS Value2, @Value1 - @Value2 AS Result, SQL_VARIANT_PROPERTY(@Value1 - @Value2, 'BaseType') AS [BaseType], SQL_VARIANT_PROPERTY(@Value1 - @Value2, 'Precision') AS [Precision], SQL_VARIANT_PROPERTY(@Value1 - @Value2, 'Scale') AS [Scale]; SELECT GREATEST(2, 4) + GREATEST(19 - 2, 10 - 4) + 1 AS ResultPrecision, GREATEST(2, 4) AS ResultScale;
こちらも、ルール通りに計算結果の有効桁数が 22 と小数点以下桁数が 4 で、DECIMAL(22, 4) になっているのがわかります。
掛け算の計算結果の有効桁数と小数点以下桁数
続いて、掛け算した結果のデータ型の有効桁数と小数点以下桁数を確認してみます。
演算 | 結果の有効桁数 | 結果の小数点以下桁数 |
---|---|---|
DECIMAL(p1, s1) * DECIMAL(p2, s2) | p1 + p2 + 1 | s1 + s2 |
DECLARE @Value1 DECIMAL(19, 2) = 111.11, @Value2 DECIMAL(10, 4) = 222.22; SELECT @Value1 AS Value1, @Value2 AS Value2, @Value1 * @Value2 AS Result, SQL_VARIANT_PROPERTY(@Value1 * @Value2, 'BaseType') AS [BaseType], SQL_VARIANT_PROPERTY(@Value1 * @Value2, 'Precision') AS [Precision], SQL_VARIANT_PROPERTY(@Value1 * @Value2, 'Scale') AS [Scale]; SELECT 19 + 10 + 1 AS ResultPrecision, 2 + 4 AS ResultScale;
ルール通りに計算結果の有効桁数が 30 と小数点以下桁数が 6 で、DECIMAL(30, 6) になっています。
割り算の計算結果の有効桁数と小数点以下桁数
割り算した結果のデータ型の有効桁数と小数点以下桁数を確認してみます。
演算 | 結果の有効桁数 | 結果の小数点以下桁数 |
---|---|---|
DECIMAL(p1, s1) / DECIMAL(p2, s2) | p1 - s1 + s2 + max(6, s1 + p2 + 1) | max(6, s1 + p2 + 1) |
DECLARE @Value1 DECIMAL(19, 2) = 111.11, @Value2 DECIMAL(10, 4) = 222.22; SELECT @Value1 AS Value1, @Value2 AS Value2, @Value1 / @Value2 AS Result, SQL_VARIANT_PROPERTY(@Value1 / @Value2, 'BaseType') AS [BaseType], SQL_VARIANT_PROPERTY(@Value1 / @Value2, 'Precision') AS [Precision], SQL_VARIANT_PROPERTY(@Value1 / @Value2, 'Scale') AS [Scale]; SELECT 19 - 2 + 4 + GREATEST(6, 2 + 10 + 1) AS ResultPrecision, GREATEST(6, 2 + 10 + 1) AS ResultScale;
計算式が少し長いですが、こちらもルール通りに有効桁数が 34、 小数点以下桁数が 13 で、DECIMAL(34, 13) になっています。
ルールの通りに計算した結果、有効桁数が 38 を超えるような場合は 38 になり、どのように切り詰められるかは追加で細かいルールが出てきますが、基本的には上記のルールで和・差・積・商の演算結果の有効桁数と小数点以下桁数が決まります。
以上、SQL Server の有効桁数と小数点以下桁数についてと、DECIMAL の計算結果の有効桁数と小数点以下桁数のルールについてご説明しました。