T-SQL 中十进制计算列的精度
Precision of decimal computed columns in T-SQL
我们曾经在数据库中有以下字段:
FieldA decimal(19, 2)
我们已将该字段更改为计算字段:
ALTER TABLE MyTable
ADD FieldA AS FieldB * FieldC
其中:
FieldB decimal(19, 2)
FieldC decimal(19, 5)
由此产生的新的FieldA
:
FieldA (Computed, decimal(38,6))
遗留代码使用 FieldA
并假设它有两位小数。因此,字符串翻译不应用格式。结果,使用新定义,FieldA
显示为六位小数,这是不可接受的。
是否可以修改计算列的精度(例如,保持原始类型 decimal(19, 2)
)或者我们是否需要在所有显示值的地方添加适当的格式?
舍入不起作用:
ADD FieldA AS ROUND(FieldB * FieldC, 2)
试试这个:
CREATE TABLE [dbo].[TEST]
(
[A] DECIMAL(19,2)
,[B] DECIMAL(19,5)
,[C] AS [A] * [B]
,[D] AS CAST([A] * [B] AS DECIMAL(19,2))
);
GO
SELECT *
FROM [sys].[columns]
WHERE [object_id] = OBJECT_ID('[dbo].[TEST]');
为什么?检查 formula 对十进制值执行操作时如何设置小数精度。
所以,我们有:
[A] DECIMAL(19,2)
[B] DECIMAL(19,5)
[C] AS [A] * [B]
公式为:
p1 + p2 + 1 => 2 + 5 + 1 => 7
s1 + s2 => 19 + 19 = > 38
但是:
In multiplication and division operations, we need precision - scale
places to store the integral part of the result. The scale might be
reduced using the following rules:
- The resulting scale is reduced to min(scale, 38 - (precision-scale)) if the integral part is less than 32, because it
can't be greater than 38 - (precision-scale). Result might be rounded
in this case.
- The scale won't be changed if it's less than 6 and if the integral part is greater than 32. In this case, overflow error might be raised
if it can't fit into decimal(38, scale)
- The scale will be set to 6 if it's greater than 6 and if the integral part is greater than 32. In this case, both integral part and
scale would be reduced and resulting type is decimal(38,6). Result
might be rounded to 6 decimal places or the overflow error will be
thrown if the integral part can't fit into 32 digits.
并且根据规则 3
,比例上限为 6
,您得到 DECIMAL(38,6)
。这就是为什么您需要将结果显式转换为目标十进制类型。
我们曾经在数据库中有以下字段:
FieldA decimal(19, 2)
我们已将该字段更改为计算字段:
ALTER TABLE MyTable
ADD FieldA AS FieldB * FieldC
其中:
FieldB decimal(19, 2)
FieldC decimal(19, 5)
由此产生的新的FieldA
:
FieldA (Computed, decimal(38,6))
遗留代码使用 FieldA
并假设它有两位小数。因此,字符串翻译不应用格式。结果,使用新定义,FieldA
显示为六位小数,这是不可接受的。
是否可以修改计算列的精度(例如,保持原始类型 decimal(19, 2)
)或者我们是否需要在所有显示值的地方添加适当的格式?
舍入不起作用:
ADD FieldA AS ROUND(FieldB * FieldC, 2)
试试这个:
CREATE TABLE [dbo].[TEST]
(
[A] DECIMAL(19,2)
,[B] DECIMAL(19,5)
,[C] AS [A] * [B]
,[D] AS CAST([A] * [B] AS DECIMAL(19,2))
);
GO
SELECT *
FROM [sys].[columns]
WHERE [object_id] = OBJECT_ID('[dbo].[TEST]');
为什么?检查 formula 对十进制值执行操作时如何设置小数精度。
所以,我们有:
[A] DECIMAL(19,2)
[B] DECIMAL(19,5)
[C] AS [A] * [B]
公式为:
p1 + p2 + 1 => 2 + 5 + 1 => 7
s1 + s2 => 19 + 19 = > 38
但是:
In multiplication and division operations, we need precision - scale places to store the integral part of the result. The scale might be reduced using the following rules:
- The resulting scale is reduced to min(scale, 38 - (precision-scale)) if the integral part is less than 32, because it can't be greater than 38 - (precision-scale). Result might be rounded in this case.
- The scale won't be changed if it's less than 6 and if the integral part is greater than 32. In this case, overflow error might be raised if it can't fit into decimal(38, scale)
- The scale will be set to 6 if it's greater than 6 and if the integral part is greater than 32. In this case, both integral part and scale would be reduced and resulting type is decimal(38,6). Result might be rounded to 6 decimal places or the overflow error will be thrown if the integral part can't fit into 32 digits.
并且根据规则 3
,比例上限为 6
,您得到 DECIMAL(38,6)
。这就是为什么您需要将结果显式转换为目标十进制类型。