SQL:删除使用 3 个连接找到的记录

SQL : Deleting records found using 3 joins

我正在使用 SQL Server 2014 数据库和 SQL Server Management Studio 来创建和 运行 查询。

表格是:

| ID | personName |
+----+------------+
| 1  |    Hamish  |
| 2  |    Morag   |
| 3  |    Ewan    |

汽车

| ID | CarName |
+----+---------+
| 1  |  Humber |
| 2  |  Austen |
| 3  |  Morris |

小工具

| ID | GadgetName |
+----+------------+
| 1  |  Cassette  |
| 2  |     CD     |
| 3  |   Radio    |

CarToPersonMap

| ID | CarID | PersonID |
+----+-------+----------+
| 1  |   1   |    1     |

CarToGadgetMap

| ID | CarID | GadgetID |
+----+-------+----------+
| 1  |   2   |    2     |

映射 table 具有适当的外键。

我想删除 Car 存在但未使用的记录。所以在上面的例子中我想用 ID = 3.

删除 Car

我有一个 SELECT 语句,它使用 3 JOIN 如下。该语句有效并且 returns 正确的行,即 CarID = 3.

SELECT * 
FROM
    (SELECT Cars.*
     FROM Cars 
     LEFT JOIN CarToGadgetMap ON Cars.ID = CarToGadgetMap.CarID
     WHERE CarToGadgetMap.CarID IS NULL) t1
JOIN
    (SELECT Cars.*
     FROM Cars 
     LEFT JOIN PersonToCarMap ON Cars.ID = PersonToCarMap.CarID
     WHERE PersonToCarMap.CarID IS NULL) t2 ON t1.ID = t2.ID

当我使用下面的代码尝试 DELETE 时,它会删除所有 3 Car 行:

DELETE Cars 
FROM
    (SELECT Cars.*
     FROM Cars 
     LEFT JOIN CarToGadgetMap ON Cars.ID = CarToGadgetMap.CarID
     WHERE CarToGadgetMap.CarID IS NULL) t1
JOIN
    (SELECT Cars.*
     FROM Cars 
     LEFT JOIN PersonToCarMap ON Cars.ID = PersonToCarMap.CarID
     WHERE PersonToCarMap.CarID IS NULL) t2 ON t1.ID = t2.ID

结果信息:

(3 row(s) affected)

并且检查显示 Cars table 中的所有 3 行已被删除。

为什么 SELECT 语句 returns 只有 1 行时所有记录都被删除?

有人能帮忙吗?

提前致谢

也许使用 WHERE 子句代替 FROM。

DELETE cars WHERE cars.id = 3 (Get your query select only the id from your logic, rather than selecting all the tables with cars.*)

您只需使用此代码即可完成。我在最后创建了一个数据库和数据来测试它。

 DELETE Cars
 FROM Cars 
 LEFT JOIN CarToPersonMap ON Cars.ID = CarToPersonMap.CarID
 LEFT JOIN CarToGadgetMap ON Cars.ID = CarToGadgetMap.CarID
 WHERE CarToPersonMap.CarID IS NULL and  CarToGadgetMap.CarID IS NULL 

当你执行DELETEUPDATE语句时,要修改的table计算如下:

  • 查看 FROM 子句(在 DELETE 中,这是第二个 FROM),用于使用该名称别名的顶级 table。
  • 否则,即使使用别名
  • ,也要查找对 Cars 的单个顶级引用
  • 否则将 table Cars 与整个 FROM 子句交叉连接

你的 DELETE 的问题是顶级作用域没有 table 命名或别名为 Cars,所以它实际上只是在整个Carstable.

你也可以这样做

DELETE Cars
WHERE NOT EXISTS (SELECT 1
    FROM CarToPersonMap cpm ON Cars.ID = cpm.CarID)
  AND NOT EXISTS (SELECT 1
    FROM CarToGadgetMap cgm ON Cars.ID = cgm.CarID);

您还可以明确指定第二个 FROM 子句

DELETE Cars
FROM Cars
WHERE ...