I run the following SQL that never commits the transaction:
rollback;
begin;
create table testing_stuff (
id serial,
num integer NOT NULL unique deferrable initially immediate
);
insert into testing_stuff (num) values (2), (1);
-- no issues with deferrable even though it swaps values
update testing_stuff set num = id;
-- fails even though I have not comitted;
update testing_stuff set num = 2;
-- this would have fixed it
update testing_stuff set num = id;
If I remove deferrable initially immediate then it fails on update testing_stuff set num = id; because each row is checked immediately. So deferrable initially immediate is definitely making something deferred.
My understanding is that since the transaction is not committed, no constraints should be checked at all here, based on the SET CONSTRAINTS documentation which says:
DEFERRED constraints are not checked until transaction commit.
If I remove the line update testing_stuff set num = 2; then everything works.
Also, if I use deferrable initially deferred then I get the deferred behavior I expect.
What am I missing about transaction boundaries and/or initially immediate here? Does initially immediate also apply to all future statements in the transaction? But then why would deferrable initially immediate avoid errors on update testing_stuff set num = id;?