2013-03-27 147 views
2

我有两个版本的PostgreSQL(8.0.4/8.1.4),并且注意到在8.1.4中,我得到一个“丢失子句错误”的以下语句:Postgresql“丢失子句错误”

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

正如你不能做一个在8.0.4与SELECT语句DELETE我使用的是直接的参考表代替,但这似乎8.1.4

将导致一个问题,就是任何人能证实这一点行为,如果可能的话提供解决方法?

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

+1

你有什么打算呢?删除另一个表中的“EXIST”记录?还有\ * MDFUSERGROUPREL \ *中的星号是什么? – wildplasser 2013-03-27 11:15:42

+0

是的,请显示原始查询的**确切文本**和错误消息的**完整文本**。 – 2013-03-27 11:20:30

+0

我删除了在stackoverflow文本编辑器中使用斜体格式的结果的asterixes – Graham 2013-03-27 11:38:26

回答

3

您依赖的是PostgreSQL旧版本的行为,该版本用于在引用未在FROM中列出的表格时隐式添加FROM子句。您可以在查询的EXPLAIN中看到此信息。

这种错误行为已从PostgreSQL中删除。它造成了错字的意外交叉产品,通常是一个非常糟糕的主意。您可以通过将add_missing_from配置参数设置为true,或者在问题查询之前使用SET语句或在postgresql.conf中将其设置为临时解决方法来重新启用它。这种向后兼容的解决方法在9.0中被删除,所以你不能用它来让你的应用程序在9.0或更高版本上运行。我故意链接到8.4版本的文档,因为参数已从较新版本中删除。

请参阅this mailing list discussion

此查询中问题的原因是您在MDFUSERGROUPREL上执行隐式连接。您应该在DELETE语句的USING子句中明确指定该表。

下面是演示显示问题和解决方法的演示:http://sqlfiddle.com/#!11/6c4b3/4 ...以及演示如何正确使用两种不同的方法:http://sqlfiddle.com/#!11/6c4b3/7。第1是一个简单的解决方法,只是增加了缺少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的例子。

+0

感谢Craig,我已经添加了参数,它现在正在工作。 – Graham 2013-03-27 11:35:02

+1

@Graham你知道这是一个*临时黑客*权利,一个* transitional *选项,直到你可以修复你的代码?它*不适用于更新的版本*?您需要修复您的查询。如果你必须设置'add_missing_from',如果可能的话,在会话中使用'SET'语句而不是在'postgresql.conf'中全局使用,所以你不会引入更多的错误。 – 2013-03-27 11:37:20

+1

@Graham另外,认真地说,让管理层醒来 - 你不只是运行一个不受支持的旧版本,你正在运行一个完全古老的补丁版本,其中包含多个已知的严重错误。至少更新到8.0.26(两年+值得修复的)或最新的8.1,然后开始计划*紧急*升级到一个现代堆栈,然后永久卡住,支持每一堆不断增长的传统垃圾,没有人关心或记住了。 – 2013-03-27 11:38:00

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=? 
; 
+0

谢谢你的回答,你有我的问题的要点。 – Graham 2013-03-27 11:39:12

+1

@Graham为未来提供快速提示:此类问题更容易回答关于查询应该执行的操作,错误的确切文本,显示的表格定义等信息。 – 2013-03-27 11:41:19