Delete using left outer join in Postgres
我正在将数据库从MySQL切换到Postgres SQL。 在MySQL中工作的选择查询在Postgres中工作,但类似的删除查询不能。
我有两个数据表,列出了某些备份文件所在的位置。 现有数据(ed)和新数据(nd)。 此语法将挑选出现有数据,这些数据可能表明文件在现有数据表中的位置,将其与相等的文件名和路径进行匹配,但没有关于它在新数据中的位置的信息:
1 2 3 4 5 6 | SELECT ed.id, ed.file_name, ed.cd_name, ed.path, nd.cd_name FROM tv_episodes AS ed LEFT OUTER JOIN DATA AS nd ON ed.file_name = nd.file_name AND ed.path = nd.path WHERE ed.cd_name = 'MediaLibraryDrive' AND nd.cd_name IS NULL; |
我希望使用以下语法运行删除查询:
1 2 3 4 5 6 | DELETE ed FROM tv_episodes AS ed LEFT OUTER JOIN DATA AS nd ON ed.file_name = nd.file_name AND ed.path = nd.path WHERE ed.cd_name = 'MediaLibraryDrive' AND nd.cd_name IS NULL; |
我尝试了
1 2 | DELETE FROM tv_episodes AS ed LEFT JOIN DATA AS nd..... |
Postgres发回
我很困难,并且使用特定于psql的连接在删除查询上找不到太多。
正如其他人所说,你不能直接在DELETE语句中LEFT JOIN。但是,您可以使用USING语句自行连接目标表的主键,然后对该自联接表保持连接。
1 2 3 4 5 6 7 8 | DELETE FROM tv_episodes USING tv_episodes AS ed LEFT OUTER JOIN DATA AS nd ON ed.file_name = nd.file_name AND ed.path = nd.path WHERE tv_episodes.id = ed.id AND ed.cd_name = 'MediaLibraryDrive' AND nd.cd_name IS NULL; |
请注意WHERE子句中tv_episodes.id上的自连接。这避免了上面提供的子查询路由。
使用
1 2 3 4 5 | DELETE FROM tv_episodes USING DATA WHERE tv_episodes.file_name = DATA.file_name AND tv_episodes.path = DATA.path AND tv_episodes.cd_name = 'MediaLibraryDrive' AND DATA.cd_name IS NULL; |
代替
1 2 3 4 5 6 | DELETE ed FROM tv_episodes AS ed LEFT OUTER JOIN DATA AS nd ON ed.file_name = nd.file_name AND ed.path = nd.path WHERE ed.cd_name = 'MediaLibraryDrive' AND nd.cd_name IS NULL; |
请试试
1 2 3 4 5 6 7 8 9 10 11 12 | DELETE FROM tv_episodes WHERE cd_name = 'MediaLibraryDrive' AND (tv_episodes.filename, tv_episodes.path IN (SELECT ed.filename, ed.path FROM tv_episodes AS ed INNER JOIN DATA AS nd ON ed.file_name = nd.file_name AND ed.path = nd.path WHERE nd.cd_name IS NULL) ) ; |
根据postgresql文档,
正如bf2020指出的那样,postgres在进行DELETE查询时不支持JOIN。建议的子查询解决方案让我想到了解决方案。从上面优化SELECT查询并将其用作DELETE查询语句的子查询:
1 2 3 4 5 6 7 8 9 | DELETE FROM tv_episodes WHERE id IN ( SELECT ed.id FROM tv_episodes AS ed LEFT OUTER JOIN DATA AS nd ON ed.file_name = nd.file_name AND ed.path = nd.path WHERE ed.cd_name = 'MediaLibraryDrive' AND nd.cd_name IS NULL ); |
对于某些数据库系统,特别是MySQL,子查询通常会耗费时间和CPU资源。根据我的经验,我试图避免使用子查询,因为这种低效率加上这种查询有时是一种简单的方法来磨练一个人的技能,比如学习JOIN语法。
由于postgre不允许使用join进行删除查询,因此以上是可行的解决方案。