1

如果连接条件进行仅对某些行有效的数据转换,但您的 where 条件将行过滤为“有效”行,那么这是一个“安全”连接条件吗?

我认为不是,但我绝不是专家,我只是想理解。AFAIK 优化器几乎可以做任何它想做的事情,只要在一天结束时所有的连接都发生并且所有的条件最终都会运行。

我试过用谷歌搜索,但没有看到任何具体的东西

SELECT *
  FROM (SELECT 1 AS ID) a
       JOIN (SELECT '1' AS ID,
                    'Y' AS FILTER
             UNION
             SELECT 'NOT_AN_INT' AS ID,
                    'N'          AS FILTER) b
         ON a.ID = CONVERT(INT, b.ID)
 WHERE b.FILTER = 'Y' 


SELECT *
  FROM (SELECT 1 AS ID) a
       JOIN (SELECT '1' AS ID,
                    'Y' AS FILTER
             UNION
             SELECT 'NOT_AN_INT' AS ID,
                    'N'          AS FILTER) b
         ON a.ID = CONVERT(INT, b.ID)
            AND b.FILTER = 'Y' 

据我了解,连接条件在内部连接上应该是可交换的,并且这两个查询应该彼此等价。然而,由于类型强制问题,第二个爆炸了。这是否证明这是一种不好的做法,您应该安全地将 a 的 ID 转换为 varchar 而不是 b 的 ID 转换为 int?或者是否有一些 ansi 规范保证这没问题?

4

1 回答 1

1

不,SQL 不保证该WHERE子句在其他子句“之前”执行。过滤可能发生在其他操作之前。过滤可能不会。

这也适用于 CTE 和子查询。SQL 优化器可以重新安排操作。SQL 是一种描述性语言,而不是一种过程语言。查询描述了结果集,而不是它是如何产生的。

您的代码似乎是 SQL Server 代码。如果是这样,只需使用TRY_CONVERT()而不是CONVERT(). 如果转换失败,则结果为NULL,这会导致大多数 -WHERE子句比较失败。

就个人而言,我认为该行为是一个错误——被过滤掉的行上的类型转换错误。我不知道 SQL 标准是否有关于这个主题的规范。

于 2019-06-28T14:07:23.753 回答