これが奇妙に感じる理由は、挿入操作の一部としてカウンターの増分を考えているためです。したがって、「何もしない」は「何も増分しない」ことを意味するはずです。あなたはこれを描いています:
- 制約に対して挿入する値を確認します
- 重複が検出された場合は中止します
- 増分シーケンス
- データを挿入
ただし、実際には、増分は挿入が試行される前に発生する必要があります。 。 SERIAL
Postgresの列はDEFAULT
として実装されています nextval()
を実行します バインドされたSEQUENCE
で関数 。 DBMSがデータに対して何かを実行する前に、列の完全なセットが必要であるため、操作の順序は次のようになります。
- シーケンスのインクリメントなど、デフォルト値を解決します
- 制約に対して挿入する値を確認します
- 重複が検出された場合は中止します
- データを挿入
これは、重複するキーが自動インクリメントフィールド自体にある場合に直感的に確認できます。
CREATE TABLE foo ( id SERIAL NOT NULL PRIMARY KEY, bar text );
-- Insert row 1
INSERT INTO foo ( bar ) VALUES ( 'test' );
-- Reset the sequence
SELECT setval(pg_get_serial_sequence('foo', 'id'), 0, true);
-- Attempt to insert row 1 again
INSERT INTO foo ( bar ) VALUES ( 'test 2' )
ON CONFLICT (id) DO NOTHING;
明らかに、これはシーケンスをインクリメントせずに競合があるかどうかを知ることができないため、「何もしない」は後に来る必要があります その増分。