Точность, масштаб и длина (Transact-SQL)
Применимо к:База данных
SQL Server Azure SQL Управляемый экземпляр 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
разрядов для хранения целой части результата. Масштаб может уменьшаться согласно приведенным ниже правилам.
- Итоговый масштаб уменьшается до
min(scale, 38 - (precision-scale))
, если целая часть короче 32 разрядов, так как он не может быть больше38 - (precision-scale)
. В этом случае результат может округляться. - Масштаб не изменяется, если он меньше 6 и если целая часть длиннее 32 разрядов. В этом случае может возникнуть ошибка переполнения, если число не помещается в decimal(38, scale).
- Масштаб будет задан равным 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)
.