转换失败。 SELECT * 来自 Person.Address WHERE ISNUMERIC(PostalCode) =1 AND PostalCode<7000
Conversion failed. SELECT * from Person.Address WHERE ISNUMERIC(PostalCode) =1 AND PostalCode<7000
它是 Microsoft SQL 服务器。
在 AdventureWorks 2012 Person.Address
table 的这一列 PostalCode
中,有数字和字符串值。
我想获得 table 行 WHERE PostalCode < 7000
这没有按预期工作:
USE [AdventureWorks2012]
SELECT *
FROM Person.Address
WHERE ISNUMERIC(PostalCode) = 1
AND PostalCode < 7000
因为我得到这个错误:
Conversion failed when converting the nvarchar value 'K4B 1T7' to data type int.
我可以做到,通过临时创建 table 像这样:
/* creating of temp table */
USE AdventureWorks2012
SELECT *
INTO temp2
FROM Person.Address
WHERE ISNUMERIC(PostalCode) = 1
/* get data from temp table */
SELECT *
FROM temp2
WHERE PostalCode < 7000
但这是一个糟糕的方法,导致生产力低下和不必要的临时工-table。
获取 table 行 WHERE PostalCode < 7000
但数据不仅有数值的更好方法是什么?
这样做的唯一安全方法是首先获取您感兴趣的字段的 ID,然后在不同的语句中加入它们,否则查询计划器可能会决定首先进行数字比较。当我们升级到 SQL Server 2008 时,我开始遇到很多以前没有发生过的问题。
但是您可以进行转换:
USE [AdventureWorks2012]
SELECT *
from Person.Address
WHERE ISNUMERIC(PostalCode) =1 AND CAST(CAST(PostalCode AS INT) AS VARCHAR)<'7000'
我已经进行了转换,以尽量避免任何可能是数字但左侧填充为 0 的数据,这可能会搞砸排序。
请注意,这不会是最好的性能,并且不会使用 PostalCode 上的索引。
您可以使用子查询来做到这一点:
select * from (
SELECT * from Person.Address WHERE ISNUMERIC(PostalCode) =1 ) t
where PostalCode<7000
返回错误是因为正在评估的条件没有短路 - 即使邮政编码不是数字,也正在评估条件 PostalCode<7000
。
相反,尝试:
SELECT *
from Person.Address
WHERE CASE WHEN PostalCode NOT LIKE '%[^0-9]%'
THEN CAST(PostalCode AS NUMERIC)
ELSE CAST(NULL AS NUMERIC)
END <7000
(根据评论更新)
文字来自70-461训练包
(Exam 70-461: Querying Microsoft SQL Server 2012):
Recall from Chapter 1 that all expressions that appear in the same
logical query processing phase—for example, the WHERE phase—are
conceptually evaluated at the same point in time. For example,
consider the following filter predicate.
WHERE propertytype = 'INT' AND CAST(propertyval AS INT) > 10
Suppose that the table being queried
holds different property values. The propertytype column represents
the type of the property (an INT, a DATE, and so on), and the
propertyval column holds the value in a character string. When
propertytype is 'INT', the value in propertyval is convertible to INT;
otherwise, not necessarily.
Some assume that unless precedence rules
dictate otherwise, predicates will be evaluated from left to right,
and that short circuiting will take place when possible. In other
words, if the first predicate propertytype = 'INT' evaluates to false,
SQL Server won’t evaluate the second predicate CAST(propertyval AS
INT) > 10 because the result is already known. Based on this
assumption, the expectation is that the query should never fail trying
to convert something that isn’t convertible.
The reality, though, is
different. SQL Server does internally support a short-circuit concept;
however, due to the all-at-once concept in the language, it is not
necessarily going to evaluate the expressions in left-to-right order.
It could decide, based on cost-related reasons, to start with the
second expression, and then if the second expression evaluates to
true, to evaluate the first expression as well. This means that if
there are rows in the table where propertytype is different than
'INT', and in those rows propertyval isn’t convertible to INT, the
query can fail due to a conversion error.
在丹麦,邮政编码的长度总是相同的,所以我会使用这个脚本来避免奇怪的问题* isnumeric 和转换问题。
它将检查 postalCode 是否有 4 位数字并比较字符串值。
SELECT *
FROM temp2
WHERE
PostalCode < '7000' and
PostalCode like '[0-9][0-9][0-9][0-9]'
*isnumeric
的奇怪问题示例
SELECT isnumeric('£1.1')
SELECT isnumeric('-')
两个returns 1
如果您使用的是 SQL Server 2012 或更新版本,您应该使用 try_convert 而不是 isnumeric。 Isnumeric 有一些有趣的问题,它 returns 1 即使对于无法转换为数字的字符串也是如此。所以这样的事情应该有效:
SELECT *
FROM Person.Address
WHERE try_convert(int, PostalCode) < 7000
如果字符串无法转换,try_convert returns null.
它是 Microsoft SQL 服务器。
在 AdventureWorks 2012 Person.Address
table 的这一列 PostalCode
中,有数字和字符串值。
我想获得 table 行 WHERE PostalCode < 7000
这没有按预期工作:
USE [AdventureWorks2012]
SELECT *
FROM Person.Address
WHERE ISNUMERIC(PostalCode) = 1
AND PostalCode < 7000
因为我得到这个错误:
Conversion failed when converting the nvarchar value 'K4B 1T7' to data type int.
我可以做到,通过临时创建 table 像这样:
/* creating of temp table */
USE AdventureWorks2012
SELECT *
INTO temp2
FROM Person.Address
WHERE ISNUMERIC(PostalCode) = 1
/* get data from temp table */
SELECT *
FROM temp2
WHERE PostalCode < 7000
但这是一个糟糕的方法,导致生产力低下和不必要的临时工-table。
获取 table 行 WHERE PostalCode < 7000
但数据不仅有数值的更好方法是什么?
这样做的唯一安全方法是首先获取您感兴趣的字段的 ID,然后在不同的语句中加入它们,否则查询计划器可能会决定首先进行数字比较。当我们升级到 SQL Server 2008 时,我开始遇到很多以前没有发生过的问题。
但是您可以进行转换:
USE [AdventureWorks2012]
SELECT *
from Person.Address
WHERE ISNUMERIC(PostalCode) =1 AND CAST(CAST(PostalCode AS INT) AS VARCHAR)<'7000'
我已经进行了转换,以尽量避免任何可能是数字但左侧填充为 0 的数据,这可能会搞砸排序。
请注意,这不会是最好的性能,并且不会使用 PostalCode 上的索引。
您可以使用子查询来做到这一点:
select * from (
SELECT * from Person.Address WHERE ISNUMERIC(PostalCode) =1 ) t
where PostalCode<7000
返回错误是因为正在评估的条件没有短路 - 即使邮政编码不是数字,也正在评估条件 PostalCode<7000
。
相反,尝试:
SELECT *
from Person.Address
WHERE CASE WHEN PostalCode NOT LIKE '%[^0-9]%'
THEN CAST(PostalCode AS NUMERIC)
ELSE CAST(NULL AS NUMERIC)
END <7000
(根据评论更新)
文字来自70-461训练包 (Exam 70-461: Querying Microsoft SQL Server 2012):
Recall from Chapter 1 that all expressions that appear in the same logical query processing phase—for example, the WHERE phase—are conceptually evaluated at the same point in time. For example, consider the following filter predicate.
WHERE propertytype = 'INT' AND CAST(propertyval AS INT) > 10
Suppose that the table being queried holds different property values. The propertytype column represents the type of the property (an INT, a DATE, and so on), and the propertyval column holds the value in a character string. When propertytype is 'INT', the value in propertyval is convertible to INT; otherwise, not necessarily.
Some assume that unless precedence rules dictate otherwise, predicates will be evaluated from left to right, and that short circuiting will take place when possible. In other words, if the first predicate propertytype = 'INT' evaluates to false, SQL Server won’t evaluate the second predicate CAST(propertyval AS INT) > 10 because the result is already known. Based on this assumption, the expectation is that the query should never fail trying to convert something that isn’t convertible.
The reality, though, is different. SQL Server does internally support a short-circuit concept; however, due to the all-at-once concept in the language, it is not necessarily going to evaluate the expressions in left-to-right order. It could decide, based on cost-related reasons, to start with the second expression, and then if the second expression evaluates to true, to evaluate the first expression as well. This means that if there are rows in the table where propertytype is different than 'INT', and in those rows propertyval isn’t convertible to INT, the query can fail due to a conversion error.
在丹麦,邮政编码的长度总是相同的,所以我会使用这个脚本来避免奇怪的问题* isnumeric 和转换问题。 它将检查 postalCode 是否有 4 位数字并比较字符串值。
SELECT *
FROM temp2
WHERE
PostalCode < '7000' and
PostalCode like '[0-9][0-9][0-9][0-9]'
*isnumeric
的奇怪问题示例SELECT isnumeric('£1.1')
SELECT isnumeric('-')
两个returns 1
如果您使用的是 SQL Server 2012 或更新版本,您应该使用 try_convert 而不是 isnumeric。 Isnumeric 有一些有趣的问题,它 returns 1 即使对于无法转换为数字的字符串也是如此。所以这样的事情应该有效:
SELECT *
FROM Person.Address
WHERE try_convert(int, PostalCode) < 7000
如果字符串无法转换,try_convert returns null.