在时态表和非时态表之间使用 EXCEPT 的 SQL 子查询给出表达式数量错误

标签 sql sql-server

问题

我需要从两个表中查找并删除其架构可能经常更改的所有相同行。在这种情况下,相等意味着行中的所有值都彼此相等,例如:

<表类=“s-表”> <标题> ID 消息 日期 = ID 消息 日期 <正文> 1 “你好” 1999年1月1日 == 1 “你好” 1999年1月1日 2 “你好” 1999年1月1日 != 2 “再见” 1999年1月1日 3 “再见” 空 == 3 “再见” 空

我想利用EXCEPT来做到这一点关键字,因为它不需要我为每列指定相等条件并在非键列名称更改时更新查询。我知道在选择中使用通配符是一种不好的代码味道,但是这两个表将始终具有相同的非隐藏列,并且以这种方式编写过程将使代码更易于维护。

可能很重要的注释,其中一个表 Table1是一个时态表,并且 Table2不是。然而,Table1 的历史记录存储在单独的表中,并且查询未利用SYSTEM_TIME (即仅查询当前数据)。

我尝试过的

Table1使用以下脚本创建:

CREATE TABLE Table1 (
  ID INT NOT NULL PRIMARY KEY
  , ValidFrom DATETIME2 GENERATED ALWAYS AS ROW START HIDDEN NOT NULL
  , ValidTo DATETIME2 GENERATED ALWAYS AS ROW END HIDDEN NOT NULL
  , PERIOD FOR SYSTEM_TIME (ValidFrom, ValidTo)
)
WITH (SYSTEM_VERSIONING = ON)

Table2使用以下脚本创建:

CREATE TABLE Table2 (
  ID INT NOT NULL PRIMARY KEY
)

我一直在尝试的是以下内容,我认为应该删除 Table1 中的所有条目Table2 中存在所有列的精确匹配:

DELETE FROM [Table1]
  WHERE [Table1].[ID] NOT IN (
    SELECT ID FROM (
      SELECT * FROM [Table1]
      EXCEPT
      SELECT * FROM [Table2]
    ) AS INNER_QUERY
  )

但是,SQL Server 出现以下意外错误:

All queries combined using a UNION, INTERSECT or EXCEPT operator must have an equal number of expressions in their target lists.

但是,以下查询可以按预期工作,没有任何问题

SELECT * FROM [Table1]
  WHERE [Table1].[ID] NOT IN (
    SELECT ID FROM (
      SELECT * FROM [Table1]
      EXCEPT
      SELECT * FROM [Table2]
    ) AS INNER_QUERY
  )

最佳答案

这显然是一个错误。

“隐藏列”抽象有时有点漏洞(other example)。

一种解决方法是将其分为两个步骤

SELECT ID
INTO   #Ids
FROM   (SELECT *
        FROM   [Table1]
        EXCEPT
        SELECT *
        FROM   [Table2]) AS INNER_QUERY

DELETE FROM [Table1]
WHERE  [Table1].[ID] NOT IN (SELECT ID
                             FROM   #Ids) 

我不清楚该 Bug 出现的情况。

DELETE抛出异常时,它是在代数过程中,调用堆栈如下所示

enter image description here

当执行SELECT ... INTO并在CRelOp_IntersectExcept::PexprBindSelf上放置断点时,调用堆栈如下所示(没有抛出错误)。也许 CRelOp_SelectQuery::BindTree 对于这些隐藏列有一些额外的逻辑(?!)。

enter image description here

关于在时态表和非时态表之间使用 EXCEPT 的 SQL 子查询给出表达式数量错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75795040/

相关文章:

mysql - 在mysql中明智地获取最大值行

sql - 在时间间隔内选择第一行和最后一行

java - 与hibernate分组的其他字段一起计数

SQL 数据库处于恢复模式

sql - 如何提高 SSMS 中 SQL 查询的执行时间?

sql - 如何根据“年”和“周”列排除周?

mysql - “截断不正确的整数值”错误

mysql - 在最后一行除外的情况下使用滞后函数

sql - 内连接 SQL 数据透视表

sql - 如何在sql中实现do-while循环