3

PostgreSQLの2つのバージョン(8.0.4 / 8.1.4)があり、8.1.4で次のステートメントに対して「MissingFrom-ClauseError」が発生することに気づきました。

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

FROMにリストされていないテーブルが参照されたときに暗黙的に句を追加していた古いバージョンのPostgreSQLの動作に依存していますFROM。これはEXPLAIN、クエリので確認できます。

この誤った機能はPostgreSQLから削除されました。それはタイプミスで偶発的な外積を引き起こし、一般的に非常に悪い考えでした。問題クエリの前のステートメントまたはでadd_missing_from構成パラメーターをtrueに設定することにより、一時的な回避策として再度有効にすることができます。この下位互換性の回避策は9.0で削除されたため、9.0以降でアプリを動作させるために使用することはできません。パラメータが後のバージョンから削除されたため、意図的に8.4バージョンのドキュメントにリンクしました。SETpostgresql.conf

このメーリングリストのディスカッションを参照してください。

このクエリの問題の原因は、で暗黙的な結合を実行していることですMDFUSERGROUPREL。ステートメントのUSING句でこのテーブルに明示的に名前を付ける必要があります。DELETE

これが問題と回避策を示すデモです:http ://sqlfiddle.com/#!11 / 6c4b3 / 4 ...そしてこれが2つの異なる方法を正しく行う方法を示すデモです: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;

EXISTS後者の2つの例では、少なくとも最新バージョンのPostgreSQLでは同じクエリプランが生成されるため、使用するか結合するかに違いはありません。

テーブルエイリアスを使用しないというクエリの元のスタイルに従いましたが、読みやすくするためにエイリアスを使用することを強くお勧めします。@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 に答える