Точность, масштаб и длина (Transact-SQL)

Применимо к: даSQL Server (все поддерживаемые версии) ДаБаза данных SQL Azure ДаУправляемый экземпляр SQL Azure

Точность представляет собой количество цифр в числе. Масштаб представляет собой количество цифр справа от десятичной запятой в числе. Например, у числа 123,45 точность равна 5, а масштаб равен 2.

В среде SQL Server минимальная точность типов данных numeric и decimal по умолчанию составляет 38 разрядов. В более ранних версиях SQL Server максимум по умолчанию составляет 28.

Длиной для числовых типов данных является количество байт, используемых для хранения числа. Для varchar и char длина символьной строки равна числу байт. Для nvarchar и nchar длина символьной строки равна числу пар байтов. Длина для типов данных binary, varbinary и image равна количеству байт. Например, тип данных int может содержать 10 разрядов, храниться в 4 байтах и не должен содержать десятичный разделитель. Тип данных int имеет точность 10, длину 4 и масштаб 0.

При сцеплении двух выражений типа char, varchar, binary или varbinary длина результирующего выражения является суммой длин двух исходных выражений и не превышает 8000 байт.

При сцеплении двух выражений типа nchar или nvarchar длина результирующего выражения является суммой длин двух исходных выражений и не превышает 4000 пар байт.

При сравнении двух выражений одного и того же типа данных, но разной длины, с помощью UNION, EXCEPT или INTERSECT длина результата будет равняться длине большего из двух выражений.

Точность и масштаб числовых типов данных, кроме decimal, фиксированы. Если арифметический оператор использует два выражения одного и того же типа, результат будет иметь тот же тип данных с точностью и масштабом, определенными для этого типа. Если оператор объединяет два выражения с различными числовыми типами данных, тип данных результата будет определяться правилами старшинства типов данных. Результат имеет точность и масштаб, определенные для этого типа данных.

В приведенной ниже таблице показано, как вычисляется точность и масштаб результата, если результат операции имеет тип decimal. Результат имеет тип decimal, если выполняется одно из следующих условий:

  • Оба выражения имеют тип decimal.
  • Одно выражение имеет тип decimal, а другое имеет тип данных со старшинством меньше, чем decimal.

Операнды выражений обозначены как выражение e1 с точностью p1 и масштабом s2 и выражение e2 с точностью p2 и масштабом s2. Точность и масштаб для любого выражения, отличного от decimal, соответствуют типу данных этого выражения. Функция max(a,b) принимает большее из значений a и b. Аналогичным образом функция min(a,b) принимает меньшее из значений a и b.

Операция Точность результата Масштаб результата *
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)

* Точность и масштаб результата имеют абсолютный максимум, равный 38. Если точность результата превышает 38, она уменьшается до 38 и уменьшается соответствующий масштаб, чтобы по возможности предотвратить усечение целой части результата. В некоторых случаях, например при умножении или делении, масштаб не уменьшается, чтобы сохранить десятичную точность, хотя при этом может возникнуть ошибка переполнения.

При выполнении операций сложения и вычитания требуется max(p1 - s1, p2 - s2) разрядов для хранения целой части числа с десятичной дробью. Если места для ее хранения недостаточно, то есть max(p1 - s1, p2 - s2) < min(38, precision) - scale, масштаб уменьшается, чтобы места для целой части хватало. Итоговый масштаб будет равен MIN(precision, 38) - max(p1 - s1, p2 - s2), поэтому дробная часть может округляться, чтобы соответствовать этому масштабу.

При выполнении операций умножения и деления требуется precision - scale разрядов для хранения целой части результата. Масштаб может уменьшаться согласно приведенным ниже правилам.

  1. Итоговый масштаб уменьшается до min(scale, 38 - (precision-scale)), если целая часть короче 32 разрядов, так как он не может быть больше 38 - (precision-scale). В этом случае результат может округляться.
  2. Масштаб не изменяется, если он меньше 6 и если целая часть длиннее 32 разрядов. В этом случае может возникнуть ошибка переполнения, если число не помещается в decimal(38, scale).
  3. Масштаб будет задан равным 6, если он больше 6 и если целая часть длиннее 32 разрядов. В этом случае уменьшаются как целая часть, так и масштаб, и итоговым типом будет decimal(38,6). Результат может округляться до 6 десятичных знаков, либо может возникнуть ошибка переполнения, когда целая часть не помещается в 32 разряда.

Примеры

Следующее выражение возвращает результат 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. Целая часть (точность – масштаб = 21) короче 32 разрядов, поэтому это случай (1) в правилах умножения и масштаб вычисляется как min(scale, 38 - (precision-scale)) = min(40, 38 - (61-40)) = 17. Тип результата — decimal(38,17).

Следующее выражение возвращает результат 0.000001, который помещается в decimal(38,6):

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 разрядов. Это случай (3) в правилах умножения, и типом результата будет decimal(38,6).

См. также раздел

Выражения (Transact-SQL)
Типы данных (Transact-SQL)