postgresql 在Postgres中使用左外连接删除

5f0d552i  于 2023-08-04  发布在  PostgreSQL
关注(0)|答案(4)|浏览(205)

我正在将数据库从MySQL切换到PostgreSQL。在MySQL中工作的选择查询在Postgres中工作,但类似的删除查询却不能。
我有两个数据表,其中列出了某些备份文件的位置。现有数据(艾德)和新数据(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 edDELETE 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的joins的delete查询。

c7rzv4ha

c7rzv4ha1#

正如其他人所指出的,不能在DELETE语句中直接使用LEFT JOIN。但是,您可以使用USING语句在主键上自连接到目标表,然后对该自连接表执行左连接。

请注意WHERE子句中tv_episodes.id上的自连接。这样就避免了上面提供的子查询路径。

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;

字符串

qvtsj1bj

qvtsj1bj2#

正如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进行delete查询,所以上面的解决方案是可行的。

qcbq4gxm

qcbq4gxm3#

使用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;

字符串

oyt4ldly

oyt4ldly4#

而不是

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文档,JOINDELETE查询中无效。您可能需要连接IN表达式的左部分和右部分。

相关问题