📄 foreign_key.sql
字号:
-- Show PKTABLE and FKTABLESELECT * from PKTABLE;SELECT * from FKTABLE;DROP TABLE FKTABLE;DROP TABLE PKTABLE;-- set default update / set null deleteCREATE TABLE PKTABLE ( ptest1 int, ptest2 int, ptest3 int, ptest4 text, PRIMARY KEY(ptest1, ptest2, ptest3) );CREATE TABLE FKTABLE ( ftest1 int DEFAULT 0, ftest2 int DEFAULT -1, ftest3 int, ftest4 int, CONSTRAINT constrname3 FOREIGN KEY(ftest1, ftest2, ftest3) REFERENCES PKTABLE ON DELETE SET NULL ON UPDATE SET DEFAULT);-- Insert Primary Key valuesINSERT INTO PKTABLE VALUES (1, 2, 3, 'test1');INSERT INTO PKTABLE VALUES (1, 3, 3, 'test2');INSERT INTO PKTABLE VALUES (2, 3, 4, 'test3');INSERT INTO PKTABLE VALUES (2, 4, 5, 'test4');INSERT INTO PKTABLE VALUES (2, -1, 5, 'test5');-- Insert Foreign Key valuesINSERT INTO FKTABLE VALUES (1, 2, 3, 1); INSERT INTO FKTABLE VALUES (2, 3, 4, 1); INSERT INTO FKTABLE VALUES (2, 4, 5, 1);INSERT INTO FKTABLE VALUES (NULL, 2, 3, 2);INSERT INTO FKTABLE VALUES (2, NULL, 3, 3);INSERT INTO FKTABLE VALUES (NULL, 2, 7, 4);INSERT INTO FKTABLE VALUES (NULL, 3, 4, 5);-- Insert a failed valuesINSERT INTO FKTABLE VALUES (1, 2, 7, 6);-- Show FKTABLESELECT * from FKTABLE;-- Try to update something that will failUPDATE PKTABLE set ptest2=5 where ptest2=2;-- Try to update something that will set defaultUPDATE PKTABLE set ptest1=0, ptest2=5, ptest3=10 where ptest2=2;UPDATE PKTABLE set ptest2=10 where ptest2=4;-- Try to update something that should not set defaultUPDATE PKTABLE set ptest2=2 WHERE ptest2=3 and ptest1=1;-- Show PKTABLE and FKTABLESELECT * from PKTABLE;SELECT * from FKTABLE;-- Try to delete something that should set nullDELETE FROM PKTABLE where ptest1=2 and ptest2=3 and ptest3=4;-- Show PKTABLE and FKTABLESELECT * from PKTABLE;SELECT * from FKTABLE;-- Try to delete something that should not set nullDELETE FROM PKTABLE where ptest2=5;-- Show PKTABLE and FKTABLESELECT * from PKTABLE;SELECT * from FKTABLE;DROP TABLE FKTABLE;DROP TABLE PKTABLE;CREATE TABLE PKTABLE (ptest1 int PRIMARY KEY);CREATE TABLE FKTABLE_FAIL1 ( ftest1 int, CONSTRAINT fkfail1 FOREIGN KEY (ftest2) REFERENCES PKTABLE);CREATE TABLE FKTABLE_FAIL2 ( ftest1 int, CONSTRAINT fkfail1 FOREIGN KEY (ftest1) REFERENCES PKTABLE(ptest2));DROP TABLE FKTABLE_FAIL1;DROP TABLE FKTABLE_FAIL2;DROP TABLE PKTABLE;-- Test for referencing column number smaller than referenced constraintCREATE TABLE PKTABLE (ptest1 int, ptest2 int, UNIQUE(ptest1, ptest2));CREATE TABLE FKTABLE_FAIL1 (ftest1 int REFERENCES pktable(ptest1));DROP TABLE FKTABLE_FAIL1;DROP TABLE PKTABLE;---- Tests for mismatched types---- Basic one column, two table setup CREATE TABLE PKTABLE (ptest1 int PRIMARY KEY);-- This next should fail, because inet=int does not existCREATE TABLE FKTABLE (ftest1 inet REFERENCES pktable);-- This should also fail for the same reason, but here we-- give the column nameCREATE TABLE FKTABLE (ftest1 inet REFERENCES pktable(ptest1));-- This should succeed, even though they are different types-- because varchar=int does existCREATE TABLE FKTABLE (ftest1 varchar REFERENCES pktable);DROP TABLE FKTABLE;-- As should thisCREATE TABLE FKTABLE (ftest1 varchar REFERENCES pktable(ptest1));DROP TABLE FKTABLE;DROP TABLE PKTABLE;-- Two columns, two tablesCREATE TABLE PKTABLE (ptest1 int, ptest2 inet, PRIMARY KEY(ptest1, ptest2));-- This should fail, because we just chose really odd typesCREATE TABLE FKTABLE (ftest1 cidr, ftest2 timestamp, FOREIGN KEY(ftest1, ftest2) REFERENCES pktable);-- Again, so should this...CREATE TABLE FKTABLE (ftest1 cidr, ftest2 timestamp, FOREIGN KEY(ftest1, ftest2) REFERENCES pktable(ptest1, ptest2));-- This fails because we mixed up the column orderingCREATE TABLE FKTABLE (ftest1 int, ftest2 inet, FOREIGN KEY(ftest2, ftest1) REFERENCES pktable);-- As does this...CREATE TABLE FKTABLE (ftest1 int, ftest2 inet, FOREIGN KEY(ftest2, ftest1) REFERENCES pktable(ptest1, ptest2));-- And again..CREATE TABLE FKTABLE (ftest1 int, ftest2 inet, FOREIGN KEY(ftest1, ftest2) REFERENCES pktable(ptest2, ptest1));-- This works...CREATE TABLE FKTABLE (ftest1 int, ftest2 inet, FOREIGN KEY(ftest2, ftest1) REFERENCES pktable(ptest2, ptest1));DROP TABLE FKTABLE;-- As does thisCREATE TABLE FKTABLE (ftest1 int, ftest2 inet, FOREIGN KEY(ftest1, ftest2) REFERENCES pktable(ptest1, ptest2));DROP TABLE FKTABLE;DROP TABLE PKTABLE;-- Two columns, same table-- Make sure this still works...CREATE TABLE PKTABLE (ptest1 int, ptest2 inet, ptest3 int, ptest4 inet, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest3,ptest4) REFERENCES pktable(ptest1, ptest2));DROP TABLE PKTABLE;-- And this, CREATE TABLE PKTABLE (ptest1 int, ptest2 inet, ptest3 int, ptest4 inet, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest3,ptest4) REFERENCES pktable);DROP TABLE PKTABLE;-- This shouldn't (mixed up columns)CREATE TABLE PKTABLE (ptest1 int, ptest2 inet, ptest3 int, ptest4 inet, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest3,ptest4) REFERENCES pktable(ptest2, ptest1));-- Nor should this... (same reason, we have 4,3 referencing 1,2 which mismatches typesCREATE TABLE PKTABLE (ptest1 int, ptest2 inet, ptest3 int, ptest4 inet, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest4,ptest3) REFERENCES pktable(ptest1, ptest2));-- Not this one either... Same as the last one except we didn't defined the columns being referenced.CREATE TABLE PKTABLE (ptest1 int, ptest2 inet, ptest3 int, ptest4 inet, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest4,ptest3) REFERENCES pktable);---- Now some cases with inheritance-- Basic 2 table case: 1 column of matching types.create table pktable_base (base1 int not null);create table pktable (ptest1 int, primary key(base1), unique(base1, ptest1)) inherits (pktable_base);create table fktable (ftest1 int references pktable(base1));-- now some ins, upd, delinsert into pktable(base1) values (1);insert into pktable(base1) values (2);-- let's insert a non-existant fktable valueinsert into fktable(ftest1) values (3);-- let's make a valid row for thatinsert into pktable(base1) values (3);insert into fktable(ftest1) values (3);-- let's try removing a row that should fail from pktabledelete from pktable where base1>2;-- okay, let's try updating all of the base1 values to *4-- which should fail.update pktable set base1=base1*4;-- okay, let's try an update that should work.update pktable set base1=base1*4 where base1<3;-- and a delete that should workdelete from pktable where base1>3;-- cleanupdrop table fktable;delete from pktable;-- Now 2 columns 2 tables, matching typescreate table fktable (ftest1 int, ftest2 int, foreign key(ftest1, ftest2) references pktable(base1, ptest1));-- now some ins, upd, delinsert into pktable(base1, ptest1) values (1, 1);insert into pktable(base1, ptest1) values (2, 2);-- let's insert a non-existant fktable valueinsert into fktable(ftest1, ftest2) values (3, 1);-- let's make a valid row for thatinsert into pktable(base1,ptest1) values (3, 1);insert into fktable(ftest1, ftest2) values (3, 1);-- let's try removing a row that should fail from pktabledelete from pktable where base1>2;-- okay, let's try updating all of the base1 values to *4-- which should fail.update pktable set base1=base1*4;-- okay, let's try an update that should work.update pktable set base1=base1*4 where base1<3;-- and a delete that should workdelete from pktable where base1>3;-- cleanupdrop table fktable;drop table pktable;drop table pktable_base;-- Now we'll do one all in 1 table with 2 columns of matching typescreate table pktable_base(base1 int not null, base2 int);create table pktable(ptest1 int, ptest2 int, primary key(base1, ptest1), foreign key(base2, ptest2) references pktable(base1, ptest1)) inherits (pktable_base);insert into pktable (base1, ptest1, base2, ptest2) values (1, 1, 1, 1);insert into pktable (base1, ptest1, base2, ptest2) values (2, 1, 1, 1);insert into pktable (base1, ptest1, base2, ptest2) values (2, 2, 2, 1);insert into pktable (base1, ptest1, base2, ptest2) values (1, 3, 2, 2);-- fails (3,2) isn't in base1, ptest1insert into pktable (base1, ptest1, base2, ptest2) values (2, 3, 3, 2);-- fails (2,2) is being referenceddelete from pktable where base1=2;-- fails (1,1) is being referenced (twice)update pktable set base1=3 where base1=1;-- this sequence of two deletes will work, since after the first there will be no (2,*) referencesdelete from pktable where base2=2;delete from pktable where base1=2;drop table pktable;drop table pktable_base;-- 2 columns (2 tables), mismatched typescreate table pktable_base(base1 int not null);create table pktable(ptest1 inet, primary key(base1, ptest1)) inherits (pktable_base);-- just generally bad types (with and without column references on the referenced table)create table fktable(ftest1 cidr, ftest2 int[], foreign key (ftest1, ftest2) references pktable);create table fktable(ftest1 cidr, ftest2 int[], foreign key (ftest1, ftest2) references pktable(base1, ptest1));-- let's mix up which columns reference whichcreate table fktable(ftest1 int, ftest2 inet, foreign key(ftest2, ftest1) references pktable);create table fktable(ftest1 int, ftest2 inet, foreign key(ftest2, ftest1) references pktable(base1, ptest1));create table fktable(ftest1 int, ftest2 inet, foreign key(ftest1, ftest2) references pktable(ptest1, base1));drop table pktable;drop table pktable_base;-- 2 columns (1 table), mismatched typescreate table pktable_base(base1 int not null, base2 int);create table pktable(ptest1 inet, ptest2 inet[], primary key(base1, ptest1), foreign key(base2, ptest2) references pktable(base1, ptest1)) inherits (pktable_base);create table pktable(ptest1 inet, ptest2 inet, primary key(base1, ptest1), foreign key(base2, ptest2) references pktable(ptest1, base1)) inherits (pktable_base);create table pktable(ptest1 inet, ptest2 inet, primary key(base1, ptest1), foreign key(ptest2, base2) references pktable(base1, ptest1)) inherits (pktable_base);create table pktable(ptest1 inet, ptest2 inet, primary key(base1, ptest1), foreign key(ptest2, base2) references pktable(base1, ptest1)) inherits (pktable_base);drop table pktable;drop table pktable_base;---- Deferrable constraints-- (right now, only FOREIGN KEY constraints can be deferred)---- deferrable, explicitely deferredCREATE TABLE pktable ( id INT4 PRIMARY KEY, other INT4);CREATE TABLE fktable ( id INT4 PRIMARY KEY, fk INT4 REFERENCES pktable DEFERRABLE);-- default to immediate: should failINSERT INTO fktable VALUES (5, 10);-- explicitely defer the constraintBEGIN;SET CONSTRAINTS ALL DEFERRED;INSERT INTO fktable VALUES (10, 15);INSERT INTO pktable VALUES (15, 0); -- make the FK insert validCOMMIT;DROP TABLE fktable, pktable;-- deferrable, initially deferredCREATE TABLE pktable ( id INT4 PRIMARY KEY, other INT4);CREATE TABLE fktable ( id INT4 PRIMARY KEY, fk INT4 REFERENCES pktable DEFERRABLE INITIALLY DEFERRED);-- default to deferred, should succeedBEGIN;INSERT INTO fktable VALUES (100, 200);INSERT INTO pktable VALUES (200, 500); -- make the FK insert validCOMMIT;-- default to deferred, explicitely make immediateBEGIN;SET CONSTRAINTS ALL IMMEDIATE;-- should failINSERT INTO fktable VALUES (500, 1000);COMMIT;DROP TABLE fktable, pktable;-- tricky behavior: according to SQL99, if a deferred constraint is set-- to 'immediate' mode, it should be checked for validity *immediately*,-- not when the current transaction commits (i.e. the mode change applies-- retroactively)CREATE TABLE pktable ( id INT4 PRIMARY KEY, other INT4);CREATE TABLE fktable ( id INT4 PRIMARY KEY, fk INT4 REFERENCES pktable DEFERRABLE);BEGIN;SET CONSTRAINTS ALL DEFERRED;-- should succeed, for nowINSERT INTO fktable VALUES (1000, 2000);-- should cause transaction abort, due to preceding errorSET CONSTRAINTS ALL IMMEDIATE;INSERT INTO pktable VALUES (2000, 3); -- too lateCOMMIT;DROP TABLE fktable, pktable;-- deferrable, initially deferredCREATE TABLE pktable ( id INT4 PRIMARY KEY, other INT4);CREATE TABLE fktable ( id INT4 PRIMARY KEY, fk INT4 REFERENCES pktable DEFERRABLE INITIALLY DEFERRED);BEGIN;-- no error hereINSERT INTO fktable VALUES (100, 200);-- error here on commitCOMMIT;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -