Difference between RESTRICT and NO ACTION
Asked Answered
B

2

55

From postgresql documentation:

RESTRICT prevents deletion of a referenced row. NO ACTION means that if any referencing rows still exist when the constraint is checked, an error is raised; this is the default behavior if you do not specify anything. (The essential difference between these two choices is that NO ACTION allows the check to be deferred until later in the transaction, whereas RESTRICT does not.)

Lets check it. Create parent and child table:

CREATE TABLE parent (
  id serial not null,
  CONSTRAINT parent_pkey PRIMARY KEY (id)
);

CREATE TABLE child (
  id serial not null,
  parent_id serial not null,
  CONSTRAINT child_pkey PRIMARY KEY (id),
  CONSTRAINT parent_fk FOREIGN KEY (parent_id)
    REFERENCES parent (id) 
    ON DELETE NO ACTION
    ON UPDATE NO ACTION
);

Populate some data:

insert into parent values(1);
insert into child values(5, 1);

And test does check is really deffered:

BEGIN;
delete from parent where id = 1; -- violates foreign key constraint, execution fails
delete from child where parent_id = 1;
COMMIT;

After first delete integrity was broken, but after second it would be restored. However, execution fails on first delete.

Same for update:

BEGIN;
update parent set id = 2 where id = 1; -- same as above
update child set parent_id = 2 where parent_id = 1;
COMMIT;

In case of deletes I can swap statements to make it work, but in case of updates I just can't do them (it is achivable via deleting both rows and inserting new versions).

Many databases don't make any difference between RESTRICT and NO ACTION while postgres pretends to do otherwise. Is it (still) true?

Bouleversement answered 17/2, 2013 at 13:38 Comment(0)
M
47

The difference only arises when you define a constraint as DEFERRABLE with an INITIALLY DEFERRED or INITIALLY IMMEDIATE mode.

See SET CONSTRAINTS.

Mellisamellisent answered 17/2, 2013 at 13:42 Comment(0)
L
3

From the The difference between RESTRICT and NO ACTION thread (2009-01-26) on the PostgreSQL general forum:

  • The original question:

From the manual:

(The essential difference between these two choices is that NO ACTION allows the check to be deferred until later in the transaction, whereas RESTRICT does not.)"

Can someone explain what this means in practical terms? Do both options generate the same error message? Does "until later in the transaction" mean that NO ACTION is not checked until an attempt is made to commit the transaction?

Bill Todd

  • The answer:

Well, you can defer a NO ACTION check until end of transaction. RESTRICT will always be checked at end of statement. Which is also the default behavior for NO ACTION, so I can see why you might not initially notice any difference. See the DEFERRABLE and INITIALLY DEFERRED options for foreign key constraints, and the SET CONSTRAINTS command.

As for why you might want a deferred check, the only practical use I can think of is to delete a referenced row in the master table, then insert a replacement row with the same key, before ending the transaction. In principle you could do that as a single UPDATE, but it might be that your application logic makes it awkward to do so.

regards, tom lane

Leatherwood answered 6/10, 2023 at 1:18 Comment(1)
Sounds like RESTRICT is slightly more restrictive, essentiallyTwayblade

© 2022 - 2024 — McMap. All rights reserved.