2013-02-17 7 views
13

Da postgresql documentation:Differenza tra LIMITARE e nessuna azione

LIMITANO impedisce cancellazione di una riga di riferimento. NO ACTION significa che se esistono ancora delle righe di riferimento quando il vincolo è selezionato, viene generato un errore; questo è il comportamento predefinito se non si specifica nulla. (La differenza essenziale tra queste due scelte è che nessuna azione permette il controllo da rinviata a più tardi nella transazione, mentre LIMITARE non.)

Lets controllarlo. Creare genitore e tabella figlio:

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 
); 

popolano alcuni dati:

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

E prova non di controllo è davvero deffered:

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

Dopo la prima cancellare l'integrità era rotto, ma dopo la seconda sarebbe stato ripristinato. Tuttavia, l'esecuzione non riesce alla prima eliminazione.

Lo stesso vale per l'aggiornamento:

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

In caso di eliminazioni posso scambiare dichiarazioni per farlo funzionare, ma in caso di aggiornamenti non riesco proprio a fare loro (è achivable tramite l'eliminazione di entrambe le file e l'inserimento nuove versioni).

Molti database non fanno alcuna differenza tra RESTRICT e NO ACTION mentre postgres finge di fare diversamente. È (ancora) vero?

risposta

14

La differenza si verifica solo quando si definisce un vincolo come DEFERRABLE con una modalità INITIALLY DEFERRED o INITIALLY IMMEDIATE.

Vedere SET CONSTRAINTS.