0

我有以下 sql 查询,它与子查询交叉应用。

SELECT 
    pm.[FileName] 
    ,REPLACE([Message], 'Upload End. Total Row:', '') cnt_char
    ,CAST(REPLACE([Message], 'Upload End. Total Row:', '') AS INT) AS row_count
FROM 
    dbo.ProductMaster pm
CROSS APPLY 
    (SELECT TOP 30 * 
     FROM dbo.ActivityLog lo 
     WHERE [Message] like 'Upload End%' 
       AND lo.[FileName] = pm.[FileName] 
     ORDER BY ActivityDate DESC) AS s

它运行良好,但如果我删除,REPLACE([Message], 'Upload End. Total Row:', '') cnt_char选择中的第二个表达式(),我会收到以下错误

消息 245,级别 16,状态 1,行 1
将 varchar 值“上传开始”转换为数据类型 int 时转换失败。

子查询中的 where 子句应明确排除 Message 为“Upload Start”的所有行,但为什么会出现此错误。我没有CROSS APPLY正确使用吗?

4

2 回答 2

1

SQL Server 可以自由地以它喜欢的任何顺序执行您的查询。这意味着它可以选择所有行,并且稍后才应用过滤器。允许以任何保证相同结果的方式这样做。

不幸的是,该保证仅涉及关系逻辑,而不涉及强制转换运算符。

一种出路是仔细检查:

case when Message like 'Upload End.%' then
    CAST(REPLACE([Message], 'Upload End. Total Row:', '') AS INT)
else null
end AS row_count
于 2013-06-18T20:37:31.070 回答
1

SQL 是一种描述性语言,而不是一种过程语言。逻辑上的方法cross apply解释了结果是如何产生的。他们没有指定执行计划。查询优化器可以自由选择生成正确结果集的任何查询计划。

您需要查看两个查询的执行计划。我的猜测是它们在根本上是不同的。在处理类型转换时,您不应该依赖where子句在转换之前进行过滤。相反,您应该使用case. 您的外部查询应如下所示:

(case when [Message] like 'Upload End. Total Row:%'
      then CAST(REPLACE([Message], 'Upload End. Total Row:', '') AS INT)
      when isnumeric([Message]) = 1
      then cast([Message] as int)
end) as row_count;
于 2013-06-18T20:38:03.387 回答