我正在将数据库从MySQL切换到Postgres SQL。在MySQL中工作的选择查询适用于Postgres,但类似的删除查询不能。
我有两个数据表,列出了某些备份文件所在的位置。现有数据(ed)和新数据(nd)。此语法将挑选出现有数据,这些数据可能表明文件在现有数据表中的位置,将其与相等的文件名和路径进行匹配,但没有关于它在新数据中的位置的信息:
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;
我希望使用以下语法运行删除查询:
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;
我已尝试DELETE ed
和DELETE ed.*
两个呈现syntax error at or near "ed"
。如果我尝试没有ed
的别名,则会出现类似的错误。如果我尝试
DELETE FROM tv_episodes AS ed
LEFT JOIN data AS nd.....
Postgres发回syntax error at or near "LEFT"
。
我很难过,并且在使用特定于psql的连接的删除查询上找不到太多。
答案 0 :(得分:44)
正如其他人所说,你不能直接在DELETE语句中LEFT JOIN。但是,您可以使用USING语句自行加入目标表的主键,然后对该自联接表保持连接。
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)
而不是
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;
请尝试
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文档, JOIN
在DELETE
查询中无效。您可能需要连接IN表达式的左右部分。
答案 2 :(得分:2)
使用DELETE... USING
语法:
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;
答案 3 :(得分:1)
正如bf2020指出的那样,postgres在进行DELETE查询时不支持JOIN。建议的子查询解决方案让我想到了解决方案。从上面优化SELECT查询并将其用作DELETE查询语句的子查询:
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进行删除查询,因此以上是可行的解决方案。