Postgresql“缺少从句错误”

时间:2013-03-27 11:04:58

标签: postgresql

我有两个版本的PostgreSQL(8.0.4 / 8.1.4)并且注意到在8.1.4中我得到了以下语句的“Missing From-Clause Error”:

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

由于你不能在8.0.4中使用SELECT语句进行DELETE,而是使用直接表引用,但这似乎导致了8.1.4中的问题

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

我知道我使用的版本已经过时且不受支持这是一个环境约束所以我不能只升级它。

2 个答案:

答案 0 :(得分:3)

您依赖于PostgreSQL的旧版本的行为,当FROM中未列出引用的表时,这些行为会隐式添加FROM子句。您将能够在查询的EXPLAIN中看到此内容。

此错误已从PostgreSQL中删除。它在拼写错误中引起了意外的交叉产品,这通常是一个非常糟糕的主意。您可以通过在问题查询之前使用SET语句或postgresql.confadd_missing_from配置参数设置为true,将其重新启用为临时解决方法。这种向后兼容性解决方法已在9.0中删除,因此您无法使用它来使您的应用程序使用9.0或更高版本。我故意链接到8.4版本的文档,因为该参数已从更高版本中删除。

请参阅this mailing list discussion

此查询中的问题原因是您正在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的例子。

答案 1 :(得分: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=?
 ;