请忽略where子句中操作数据的明显问题。我知道!我在做这个工作。但是,在进行此操作时,我发现此查询运行:
SELECT *
FROM PatientDistribution
WHERE InvoiceNumber LIKE'PEX%'
AND ISNUMERIC(CheckNumber) = 1
AND CONVERT(BIGINT,CheckNumber) <> TransactionId
这个不是:
SELECT *
FROM PatientDistribution
WHERE InvoiceNumber LIKE'PEX%'
AND CONVERT(BIGINT,CheckNumber) <> TransactionId
AND ISNUMERIC(CheckNumber) = 1
两个查询之间的唯一区别是WHERE子句中的项目顺序。我的印象是SQL Server查询优化器会让我担心不必担心这一点。
返回的错误是:将数据类型varchar转换为bigint时出错。
答案 0 :(得分:1)
你是对的,条件的顺序无关紧要。
AND ISNUMERIC(CheckNumber) = 1
并且因此解除了不匹配的行,那么AND CONVERT(BIGINT,CheckNumber) <> TransactionId
将起作用(对于例外情况,请参阅scsimon的答案)。AND CONVERT(BIGINT,CheckNumber) <> TransactionId
之前处理AND ISNUMERIC(CheckNumber) = 1
,则可能会收到错误。你的第一个查询有效,第二个查询不是运气问题。反过来也可以这样。
您可以强制一个条件在另一个条件之前执行:
SELECT *
FROM
(
SELECT *
FROM PatientDistribution
WHERE InvoiceNumber LIKE 'PEX%'
AND ISNUMERIC(CheckNumber) = 1
) num_only
WHERE CONVERT(BIGINT,CheckNumber) <> TransactionId;
答案 1 :(得分:0)
你很幸运第一个工作,因为你是正确的,你在where子句中列出的顺序无关紧要。 SQL是一种声明性语言,意味着您告诉引擎应该发生什么,而不是如何。因此,您的查询并未使用我怀疑的相同查询计划执行。当然,您可以在一定程度上影响优化器的功能。使用CTE时,您还会注意到此类问题。例如:
declare @table table(columnName varchar(64))
insert into @table
values
('1')
,('1e4')
;with cte as(
select columnName
from @table
where isnumeric(columnName) = 1)
select
cast(columnName as decimal(32,16))
from cte
上面的代码片段假设第二个语句是在CTE语句的结果/子集上运行的。但是,您无法确保这种情况发生,并且您仍然可能在第二个语句上遇到类型/转换错误。
更重要的是,您应该知道ISNUMERIC()
在很大程度上被误用了。人们通常认为如果它返回1则可以转换为小数或int。但事实并非如此。它只是检查它是否是有效的数字类型。例如:
select
isnumeric('1e4')
,isnumeric('$')
,isnumeric('1,123,456')
正如您所看到的,这些评估为true,但会使您在帖子中的转化失败。
旁注,您的索引可能是第一个实际上没有错误的原因。