gpt4 book ai didi

SQL Server 错误或功能?十进制数转换

转载 作者:行者123 更新时间:2023-12-02 01:56:30 24 4
gpt4 key购买 nike

在处理小数和数字数据类型时,我在 SQL Server 中遇到一些奇怪的行为。我有一个计算特定值 (4.250) 的公式,并且在所有情况下都使用相同的舍入和转换操作。但是,根据获取值的方式,我会得到不同的结果。

例如,如果我从表中获取值,则会得到与从临时表、变量表或硬编码值中获取值不同的结果。所有情况下的公式完全相同,但结果不同。

我怀疑这是由于每个上下文中值的存储或操作方式不同造成的。这是 SQL Server 的已知问题吗?有没有办法确保在所有上下文中获得一致的结果?

任何帮助或建议将不胜感激。谢谢!

-- normal table
CREATE TABLE [dbo].[value]
(
[val] [decimal] (5, 3) NOT NULL
)
INSERT INTO [value] VALUES (4.250 )
SELECT ROUND(CAST(val * 0.01 / 12 AS DECIMAL(15, 9)), 9) AS val FROM [value] AS pr

-- inline query from normal table
SELECT * FROM (SELECT ROUND(CAST(val * 0.01 / 12 AS DECIMAL(15, 9)), 9) AS val FROM [value] AS pr) a

-- record without table
SELECT ROUND(CAST(4.250 * 0.01 / 12 AS DECIMAL(15, 9)), 9) AS val

-- table variable
DECLARE @value AS TABLE (
val [decimal] (5, 3)
);

INSERT INTO @value VALUES (4.250 )

SELECT ROUND(CAST(val * 0.01 / 12 AS DECIMAL(15, 9)), 9) AS val FROM @value

-- temp table
CREATE TABLE #value
(
val [decimal] (5, 3)
)
INSERT INTO #value VALUES (4.250 )
SELECT ROUND(CAST(val * 0.01 / 12 AS DECIMAL(15, 9)), 9) AS val FROM #value AS pr

-- all records together
SELECT ROUND(CAST(val * 0.01 / 12 AS DECIMAL(15, 9)), 9) AS val FROM [value] AS pr
UNION ALL
SELECT ROUND(CAST(4.250 * 0.01 / 12 AS DECIMAL(15, 9)), 9) AS val
UNION ALL
SELECT ROUND(CAST(val * 0.01 / 12 AS DECIMAL(15, 9)), 9) AS val FROM @value
UNION ALL
SELECT ROUND(CAST(val * 0.01 / 12 AS DECIMAL(15, 9)), 9) AS val FROM #value AS pr

DROP TABLE #value;
DROP TABLE [dbo].[value];

结果是:

enter image description here

最佳答案

这似乎是因为您没有在硬编码该值的所有地方指定 4.250 的数据类型,以及混合数据类型 decimal(5,3)decimal(15 ,9) 在表声明和强制转换语句中。

请注意,在各处指定相同的精度:

-- normal table
CREATE TABLE [dbo].[value]
(
[val] DECIMAL(15, 9) NOT NULL
)

INSERT INTO [value]
SELECT CAST(4.250 AS DECIMAL(15, 9))

SELECT ROUND(CAST(val * 0.01 / 12 AS DECIMAL(15, 9)), 9) AS val
FROM [value] AS pr

-- inline query from normal table
SELECT *
FROM (SELECT ROUND(CAST(val * 0.01 / 12 AS DECIMAL(15, 9)), 9) AS val
FROM [value] AS pr) a

-- record without table
SELECT ROUND(CAST(CAST(4.250 AS DECIMAL(15, 9)) * 0.01 / 12 AS DECIMAL(15, 9)), 9) AS val

-- table variable
DECLARE @value AS TABLE
(
val [DECIMAL] (15, 9)
);

INSERT INTO @value
SELECT CAST(4.250 AS DECIMAL(15, 9))

SELECT ROUND(CAST(val * 0.01 / 12 AS DECIMAL(15, 9)), 9) AS val
FROM @value

-- temp table
CREATE TABLE #value
(
val [DECIMAL] (15, 9)
)

INSERT INTO #value
SELECT CAST(4.250 AS DECIMAL(15, 9))

SELECT ROUND(CAST(val * 0.01 / 12 AS DECIMAL(15, 9)), 9) AS val
FROM #value AS pr

-- all records together
SELECT ROUND(CAST(val * 0.01 / 12 AS DECIMAL(15, 9)), 9) AS val
FROM [value] AS pr
UNION ALL
SELECT ROUND(CAST(CAST(4.250 AS DECIMAL(15, 9)) * 0.01 / 12 AS DECIMAL(15, 9)), 9) AS val
UNION ALL
SELECT ROUND(CAST(val * 0.01 / 12 AS DECIMAL(15, 9)), 9) AS val
FROM @value
UNION ALL
SELECT ROUND(CAST(val * 0.01 / 12 AS DECIMAL(15, 9)), 9) AS val
FROM #value AS pr

DROP TABLE #value;

DROP TABLE [dbo].[value];

每一行都会得到相同的结果:

0.003541667

进一步说明:

您可以通过将硬编码数值填充到变体中来测试其数据类型:

DECLARE @var SQL_VARIANT;

SELECT @var = 4.250

SELECT SQL_VARIANT_PROPERTY(@var, 'BaseType'),
SQL_VARIANT_PROPERTY(@var, 'Precision'),
SQL_VARIANT_PROPERTY(@var, 'Scale');

这会在我的本地 SQL Server 框中返回numeric(4,3)。 (数字和十进制是 same thing )

编辑#2:进一步挖掘

仅举第一个例子:

CREATE TABLE [dbo].[value]
(
[val] [decimal] (5, 3) NOT NULL
)
INSERT INTO [value] VALUES (4.250 )

SELECT ROUND(CAST(val * 0.01 / 12 AS DECIMAL(15, 9)), 9) AS val FROM [value] AS pr

-- inline query from normal table
SELECT * FROM (SELECT ROUND(CAST(val * 0.01 / 12 AS DECIMAL(15, 9)), 9) AS val FROM [value] AS pr) a

DROP TABLE VALUE

进一步挖掘后,执行计划有所不同 - 第一个语句被参数化,而子查询版本则不然:

execution plans

如果您查看属性窗口:

enter image description here

它没有列出这些参数的数据类型,但使用相同的技巧将值 0.0112 填充到变体中最终会得到数据类型 分别为 numeric(2,2)int

如果将第二个语句中的硬编码值转换为这些数据类型:

SELECT * FROM (SELECT ROUND(CAST(val * CAST(0.01 AS NUMERIC(2,2)) / CAST(12 AS INT) AS DECIMAL(15, 9)), 9) AS val FROM [value] AS pr) a

这两个语句得到相同的结果。为什么它决定参数化 select 而不是子查询,参数的数据类型实际上是什么,以及在第二个语句中硬编码值通常被视为什么数据类型......对我来说仍然是个谜。我们可能需要询问具有 SQL Server 引擎内部知识的人。

关于SQL Server 错误或功能?十进制数转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45729377/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com