9

下面是我正在使用的表结构和数据的一个子集。

CREATE TABLE #Test
(
     Val varchar(5)
    ,Type varchar(5)
)

INSERT #Test VALUES ('Yes','Text')
INSERT #Test VALUES ('10','Int')
INSERT #Test VALUES ('10.00','Float')
INSERT #Test VALUES ('9.00','Float')
INSERT #Test VALUES ('9','Int')

我想编写一个查询,让我知道列“Val”是否<= 9.00(必须是数字数据类型)。我通过执行以下操作来做到这一点:

SELECT *
FROM
    (
        SELECT Val
        FROM #Test
        WHERE Type = 'Int'
    ) IntsOnly
WHERE IntsOnly.Val <= 9.00

这给了我一个算术溢出错误。但是,如果我排除值为“10”的数据行:

SELECT *
FROM
    (
        SELECT Val
        FROM #Test
        WHERE Type = 'Int'
        AND Val <> '10'
    ) IntsOnly
WHERE IntsOnly.Val <= 9.00

它可以正常工作。我的问题不是如何解决这个问题,因为我知道我可以简单地将数据转换为我需要的格式。

我的问题是为什么“Val”列中的“10”值返回错误。当然,逻辑应该只返回“False”并简单地排除行,因为“10”(我假设它是隐式转换的)大于 9.00。

谢谢。

4

3 回答 3

17

这会产生算术溢出,因为它试图将Val列隐式转换为 NUMERIC(3,2),这自然会溢出像 10 这样的 2 位值。

它使用 NUMERIC(3,2) 作为目标类型和大小,因为这是9.00看起来适合的最小数字。

当然,解决方案是使用显式 CASTing 而不是隐式进行

于 2012-10-31T15:32:12.273 回答
4

来自BOL

在 Transact-SQL 语句中,带小数点的常量会自动转换为数值数据值,使用所需的最小精度和小数位数。例如,常数 12.345 被转换为精度为 5、小数位数为 3 的数值。

这意味着您的常量9.00将具有1 的精度和 0的小数位数、3 的精度和 2 的小数位数,因此它无法存储值10,它需要的最小精度为2 + scale

您需要IntsOnly.Val用 aCAST或包裹CONVERT以指定正确的精度和比例。

于 2012-10-31T15:31:14.620 回答
-1

试试这个……它对我有用

     CAST(CAST(@UR_VARIABLE AS FLOAT) AS NUMERIC(3,2))
于 2019-10-01T08:41:59.737 回答