在 WHERE 子句中将 nvarchar 转换为 bigint 时出错,但在 SELECT 中有效

Bit*_*itz 1 sql t-sql sql-server casting sql-server-2019

我正在努力实现以下目标:

得到的所有字段值,其中FieldValue大于100时的值被存储为一个数字。

一个值是否存储为数字的指示符由字段类型给出,这是另一个 where 子句。

我面临的问题是,当我尝试在 WHERE 语句中进行数据字段转换时,它失败了。

我跑:

SELECT FieldValue FROM CARData A
JOIN Fields B ON A.FieldId = B.FieldId
WHERE FieldTypeId = 3 AND FieldValue IS NOT NULL 
Run Code Online (Sandbox Code Playgroud)

这将返回以下预期结果:

结果

但是,如果我添加了 WHERE 子句以按值过滤:

SELECT FieldValue FROM CARData A
JOIN Fields B ON A.FieldId = B.FieldId
WHERE FieldTypeId = 3 AND FieldValue IS NOT NULL 
AND CAST(FieldValue AS BIGINT) > 100
Run Code Online (Sandbox Code Playgroud)

它抛出错误:

将数据类型 nvarchar 转换为 bigint 时出错。

我有点理解问题是什么 - 它试图将表中的所有值转换为 bigint 并且在遇到非数字值时失败。

我试图通过在第二个查询中嵌套第一个查询来解决这个问题,如下所示:

SELECT RESULT.FieldValue FROM (
SELECT FieldValue FROM CARData A
JOIn Fields B ON A.FieldId = B.FieldId
WHERE 
FieldTypeId = 3 
AND FieldValue IS NOT NULL 
AND ISNUMERIC(A.FieldValue) = 1) RESULT
WHERE CAST(FieldValue AS BIGINT) > 100
Run Code Online (Sandbox Code Playgroud)

但即使这样也不会返回上述错误以外的任何内容。

all*_*ran 5

虽然更改查询结构确实会导致 SQL 选择不同的计划,但您应该限制该技术以尝试帮助优化器选择一个高性能计划。这样做的原因是,如果逻辑的成功执行取决于特定的计划选择,那么当 SQL 决定选择不同的计划时,您的查询可能在今天工作但明天(或在生产中)失败。

幸运的是,在这里您不必依赖它!使用try_cast

SELECT FieldValue FROM CARData A
JOIN Fields B ON A.FieldId = B.FieldId
WHERE FieldTypeId = 3 
AND TRY_CAST(FieldValue AS BIGINT) > 100
Run Code Online (Sandbox Code Playgroud)

我也很好奇……这是 SQL 课程的一部分吗?如果是这样,请告诉您的教师访问 StackOverflow,以便我们可以告诉他们停止教学生使用 EAV。除非重点是要向您展示它们有多可怕!:)

  • @Bitz 不要用驳船杆触碰 `ISNUMERIC`,它在很多方面都被破坏了 `ISNUMERIC(-.)` 返回 1 (3认同)