Důvod, proč se vám to zdá divné, je ten, že uvažujete o zvýšení na počítadle jako o součásti operace vkládání, a proto by „NEDĚLAT NIC“ mělo znamenat „nic nezvyšovat“. Představujete si toto:
- Zkontrolujte hodnoty, které chcete vložit proti omezení
- Pokud je detekován duplikát, přerušte jej
- Posloupnost přírůstků
- Vložte data
Ale ve skutečnosti musí ke zvýšení dojít před pokusem o vložení . SERIAL
sloupec v Postgresu je implementován jako DEFAULT
který provede nextval()
funkce na vázané SEQUENCE
. Než bude DBMS moci s daty cokoli dělat, musí mít kompletní sadu sloupců, takže pořadí operací je toto:
- Vyřešte výchozí hodnoty, včetně zvýšení sekvence
- Zkontrolujte hodnoty, které chcete vložit proti omezení
- Pokud je detekován duplikát, přerušte jej
- Vložte data
To lze intuitivně vidět, pokud je duplicitní klíč v samotném poli automatického přírůstku:
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;
Je zřejmé, že toto nemůže bez zvýšení sekvence zjistit, zda došlo ke konfliktu, takže „nedělat nic“ musí přijít po tento přírůstek.