3

我有两个版本的 PostgreSQL(8.0.4 / 8.1.4),并注意到在 8.1.4 中,我收到以下语句的“Missing From-Clause 错误”:

DELETE FROM MDFUSERGROUPREL_DELETED 
WHERE userid = MDFUSERGROUPREL.userid 
AND usergroupid = MDFUSERGROUPREL.usergroupid 
AND userid=?

由于您不能在 8.0.4 中使用 SELECT 语句执行 DELETE,因此我使用的是直接表引用,但这似乎在 8.1.4 中导致了问题

是否有人能够确认这种行为,并在可能的情况下提供解决方法?

我知道我使用的版本是旧的并且不支持这是一个环境限制,所以不,我不能只是升级它。

4

2 回答 2

4

您依赖于旧版本 PostgreSQL 的行为,FROM当引用未在FROM. 您将能够在EXPLAIN您的查询中看到这一点。

此错误功能已从 PostgreSQL 中删除。它在拼写错误上造成了意外的交叉产品,通常是一个非常糟糕的主意。您可以通过在问题查询之前使用语句将add_missing_from配置参数设置为 true或在. 这种向后兼容的解决方法已在 9.0 中删除,因此您无法使用它来让您的应用程序与 9.0 或更高版本一起工作。我特意链接到 8.4 版本的文档,因为该参数已从更高版本中删除。SETpostgresql.conf

请参阅此邮件列表讨论

此查询中问题的原因是您正在对MDFUSERGROUPREL. 您应该在语句的USING子句中明确命名此表DELETE

这是一个演示问题和解决方法的演示:http ://sqlfiddle.com/#!11/6c4b3/4 ...这是一个演示如何正确地以两种不同的方式进行操作: http: //sqlfiddle.com/# !11/6c4b3/7。第一个是一个简单的修复,它只是将缺少的 from 子句添加到查询并修复生成的列名冲突:

DELETE FROM MDFUSERGROUPREL_DELETED
USING MDFUSERGROUPREL
WHERE MDFUSERGROUPREL_DELETED.userid = MDFUSERGROUPREL.userid 
AND MDFUSERGROUPREL_DELETED.usergroupid = MDFUSERGROUPREL.usergroupid 
AND MDFUSERGROUPREL_DELETED.userid=1;

您会发现后两个示例至少在现代版本的 PostgreSQL 上导致相同的查询计划,因此无论您使用EXISTS还是连接都没有区别。

我在不使用表别名方面遵循了您查询的原始样式,但我强烈建议您使用别名以提高可读性。请参阅@wildplasser 的示例。

于 2013-03-27T11:17:49.983 回答
2

不了解您的确切意图,在我看来仍然exists可以解决问题:

DELETE FROM MDFUSERGROUPREL_DELETED del
WHERE EXISTS (SELECT *
    FROM MDFUSERGROUPRE ex
    WHERE ex.userid = del.userid 
    AND ex.usergroupid = del.usergroupid
    ) 
AND del.userid=?
 ;
于 2013-03-27T11:21:25.060 回答