PG9がアルファ状態のときにほぼ同じポイントを上げたことを覚えています。 Tom Lane(著名なPGコア開発者)からの回答は次のとおりです。
https://archives.postgresql.org/pgsql-general/2010-01/msg00221.php
つまり、修正されません。
現在の動作はバグであるというあなたの提案に同意することは言うまでもありません。反対の角度から見てください。これは、NOT DEFERRABLEの動作です。 それは正しくありません。
実際、UPDATEの最後に制約が満たされるため、このUPDATEでの制約違反はどのような場合でも発生しないはずです。コマンドの最後の状態が重要です。単一のステートメントの実行中の中間状態は、ユーザーに公開されるべきではありません。
PostgreSQLは、すべての行が更新された後に重複をチェックし、最初の重複の直後に失敗することによって、延期不可能な制約を実装しているようです。これは本質的に欠陥があります。しかし、これは既知の問題であり、おそらくPostgreSQLと同じくらい古いものです。現在、この回避策は、正確にDEFERRABLE制約を使用することです。そして、それが失敗しないのであなたがそれを不十分であると見ているという点で皮肉なことがありますが、どういうわけかそれはそもそも失敗の解決策であるはずです!
PostgreSQL9.1以降の現状の概要
-
NOT DEFERRABLEUNIQUEまたはPRIMARY KEY制約は各行の後にチェックされます 。 -
DEFERRABLEIMMEDIATEに設定された制約 (INITIALLY IMMEDIATEまたはSET CONSTRAINTS経由 )各ステートメントの後にチェックされます 。 -
DEFERRABLEDEFERREDに設定された制約 (INITIALLY DEFERREDまたはSET CONSTRAINTS経由 )各トランザクションの後にチェックされます 。
UNIQUEの特別な扱いに注意してください /PRIMARY KEY 制約。CREATE TABLEのマニュアルページを引用する :
延期できない制約は、すべてのコマンドの直後にチェックされます。 。
互換性のさらに下に記載されていますが Non-deferred uniqueness constraintsの下のセクション :
UNIQUEの場合 またはPRIMARY KEY制約は延期できません。PostgreSQLは一意性をすぐにチェックします 行が挿入または変更されたときはいつでも。 SQL標準では、一意性はステートメントの最後でのみ強制する必要があるとされています。;これは、たとえば、1つのコマンドが複数のキー値を更新する場合に違いを生みます。標準に準拠した動作を実現するには、制約をDEFERRABLEとして宣言します。 ただし、延期されません(つまり、INITIALLY IMMEDIATE)。これは、即時の一意性チェックよりも大幅に遅くなる可能性があることに注意してください。
大胆な強調鉱山。
FOREIGN KEYが必要な場合 列を参照するための制約、DEFERRABLE (ドキュメントごとに)次の理由でオプションではありません:
参照される列は、参照されるテーブル内の延期できない一意または主キー制約の列である必要があります。