mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-10-01 21:21:18 +02:00
feb4f44d29
terms, add some clarifications, fix some untranslatable attempts at dynamic message building.
1075 lines
45 KiB
Plaintext
1075 lines
45 KiB
Plaintext
--
|
|
-- FOREIGN KEY
|
|
--
|
|
-- MATCH FULL
|
|
--
|
|
-- First test, check and cascade
|
|
--
|
|
CREATE TABLE PKTABLE ( ptest1 int PRIMARY KEY, ptest2 text );
|
|
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "pktable_pkey" for table "pktable"
|
|
CREATE TABLE FKTABLE ( ftest1 int REFERENCES PKTABLE MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE, ftest2 int );
|
|
NOTICE: CREATE TABLE will create implicit triggers for foreign-key checks
|
|
-- Insert test data into PKTABLE
|
|
INSERT INTO PKTABLE VALUES (1, 'Test1');
|
|
INSERT INTO PKTABLE VALUES (2, 'Test2');
|
|
INSERT INTO PKTABLE VALUES (3, 'Test3');
|
|
INSERT INTO PKTABLE VALUES (4, 'Test4');
|
|
INSERT INTO PKTABLE VALUES (5, 'Test5');
|
|
-- Insert successful rows into FK TABLE
|
|
INSERT INTO FKTABLE VALUES (1, 2);
|
|
INSERT INTO FKTABLE VALUES (2, 3);
|
|
INSERT INTO FKTABLE VALUES (3, 4);
|
|
INSERT INTO FKTABLE VALUES (NULL, 1);
|
|
-- Insert a failed row into FK TABLE
|
|
INSERT INTO FKTABLE VALUES (100, 2);
|
|
ERROR: insert or update on table "fktable" violates foreign key constraint "$1"
|
|
DETAIL: Key (ftest1)=(100) is not present in table "pktable".
|
|
-- Check FKTABLE
|
|
SELECT * FROM FKTABLE;
|
|
ftest1 | ftest2
|
|
--------+--------
|
|
1 | 2
|
|
2 | 3
|
|
3 | 4
|
|
| 1
|
|
(4 rows)
|
|
|
|
-- Delete a row from PK TABLE
|
|
DELETE FROM PKTABLE WHERE ptest1=1;
|
|
-- Check FKTABLE for removal of matched row
|
|
SELECT * FROM FKTABLE;
|
|
ftest1 | ftest2
|
|
--------+--------
|
|
2 | 3
|
|
3 | 4
|
|
| 1
|
|
(3 rows)
|
|
|
|
-- Update a row from PK TABLE
|
|
UPDATE PKTABLE SET ptest1=1 WHERE ptest1=2;
|
|
-- Check FKTABLE for update of matched row
|
|
SELECT * FROM FKTABLE;
|
|
ftest1 | ftest2
|
|
--------+--------
|
|
3 | 4
|
|
| 1
|
|
1 | 3
|
|
(3 rows)
|
|
|
|
DROP TABLE FKTABLE;
|
|
DROP TABLE PKTABLE;
|
|
--
|
|
-- check set NULL and table constraint on multiple columns
|
|
--
|
|
CREATE TABLE PKTABLE ( ptest1 int, ptest2 int, ptest3 text, PRIMARY KEY(ptest1, ptest2) );
|
|
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "pktable_pkey" for table "pktable"
|
|
CREATE TABLE FKTABLE ( ftest1 int, ftest2 int, ftest3 int, CONSTRAINT constrname FOREIGN KEY(ftest1, ftest2)
|
|
REFERENCES PKTABLE MATCH FULL ON DELETE SET NULL ON UPDATE SET NULL);
|
|
NOTICE: CREATE TABLE will create implicit triggers for foreign-key checks
|
|
-- Insert test data into PKTABLE
|
|
INSERT INTO PKTABLE VALUES (1, 2, 'Test1');
|
|
INSERT INTO PKTABLE VALUES (1, 3, 'Test1-2');
|
|
INSERT INTO PKTABLE VALUES (2, 4, 'Test2');
|
|
INSERT INTO PKTABLE VALUES (3, 6, 'Test3');
|
|
INSERT INTO PKTABLE VALUES (4, 8, 'Test4');
|
|
INSERT INTO PKTABLE VALUES (5, 10, 'Test5');
|
|
-- Insert successful rows into FK TABLE
|
|
INSERT INTO FKTABLE VALUES (1, 2, 4);
|
|
INSERT INTO FKTABLE VALUES (1, 3, 5);
|
|
INSERT INTO FKTABLE VALUES (2, 4, 8);
|
|
INSERT INTO FKTABLE VALUES (3, 6, 12);
|
|
INSERT INTO FKTABLE VALUES (NULL, NULL, 0);
|
|
-- Insert failed rows into FK TABLE
|
|
INSERT INTO FKTABLE VALUES (100, 2, 4);
|
|
ERROR: insert or update on table "fktable" violates foreign key constraint "constrname"
|
|
DETAIL: Key (ftest1,ftest2)=(100,2) is not present in table "pktable".
|
|
INSERT INTO FKTABLE VALUES (2, 2, 4);
|
|
ERROR: insert or update on table "fktable" violates foreign key constraint "constrname"
|
|
DETAIL: Key (ftest1,ftest2)=(2,2) is not present in table "pktable".
|
|
INSERT INTO FKTABLE VALUES (NULL, 2, 4);
|
|
ERROR: insert or update on table "fktable" violates foreign key constraint "constrname"
|
|
DETAIL: MATCH FULL does not allow mixing of null and nonnull key values.
|
|
INSERT INTO FKTABLE VALUES (1, NULL, 4);
|
|
ERROR: insert or update on table "fktable" violates foreign key constraint "constrname"
|
|
DETAIL: MATCH FULL does not allow mixing of null and nonnull key values.
|
|
-- Check FKTABLE
|
|
SELECT * FROM FKTABLE;
|
|
ftest1 | ftest2 | ftest3
|
|
--------+--------+--------
|
|
1 | 2 | 4
|
|
1 | 3 | 5
|
|
2 | 4 | 8
|
|
3 | 6 | 12
|
|
| | 0
|
|
(5 rows)
|
|
|
|
-- Delete a row from PK TABLE
|
|
DELETE FROM PKTABLE WHERE ptest1=1 and ptest2=2;
|
|
-- Check FKTABLE for removal of matched row
|
|
SELECT * FROM FKTABLE;
|
|
ftest1 | ftest2 | ftest3
|
|
--------+--------+--------
|
|
1 | 3 | 5
|
|
2 | 4 | 8
|
|
3 | 6 | 12
|
|
| | 0
|
|
| | 4
|
|
(5 rows)
|
|
|
|
-- Delete another row from PK TABLE
|
|
DELETE FROM PKTABLE WHERE ptest1=5 and ptest2=10;
|
|
-- Check FKTABLE (should be no change)
|
|
SELECT * FROM FKTABLE;
|
|
ftest1 | ftest2 | ftest3
|
|
--------+--------+--------
|
|
1 | 3 | 5
|
|
2 | 4 | 8
|
|
3 | 6 | 12
|
|
| | 0
|
|
| | 4
|
|
(5 rows)
|
|
|
|
-- Update a row from PK TABLE
|
|
UPDATE PKTABLE SET ptest1=1 WHERE ptest1=2;
|
|
-- Check FKTABLE for update of matched row
|
|
SELECT * FROM FKTABLE;
|
|
ftest1 | ftest2 | ftest3
|
|
--------+--------+--------
|
|
1 | 3 | 5
|
|
3 | 6 | 12
|
|
| | 0
|
|
| | 4
|
|
| | 8
|
|
(5 rows)
|
|
|
|
DROP TABLE PKTABLE CASCADE;
|
|
NOTICE: drop cascades to constraint constrname on table fktable
|
|
DROP TABLE FKTABLE;
|
|
--
|
|
-- check set default and table constraint on multiple columns
|
|
--
|
|
CREATE TABLE PKTABLE ( ptest1 int, ptest2 int, ptest3 text, PRIMARY KEY(ptest1, ptest2) );
|
|
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "pktable_pkey" for table "pktable"
|
|
CREATE TABLE FKTABLE ( ftest1 int DEFAULT -1, ftest2 int DEFAULT -2, ftest3 int, CONSTRAINT constrname2 FOREIGN KEY(ftest1, ftest2)
|
|
REFERENCES PKTABLE MATCH FULL ON DELETE SET DEFAULT ON UPDATE SET DEFAULT);
|
|
NOTICE: CREATE TABLE will create implicit triggers for foreign-key checks
|
|
-- Insert a value in PKTABLE for default
|
|
INSERT INTO PKTABLE VALUES (-1, -2, 'The Default!');
|
|
-- Insert test data into PKTABLE
|
|
INSERT INTO PKTABLE VALUES (1, 2, 'Test1');
|
|
INSERT INTO PKTABLE VALUES (1, 3, 'Test1-2');
|
|
INSERT INTO PKTABLE VALUES (2, 4, 'Test2');
|
|
INSERT INTO PKTABLE VALUES (3, 6, 'Test3');
|
|
INSERT INTO PKTABLE VALUES (4, 8, 'Test4');
|
|
INSERT INTO PKTABLE VALUES (5, 10, 'Test5');
|
|
-- Insert successful rows into FK TABLE
|
|
INSERT INTO FKTABLE VALUES (1, 2, 4);
|
|
INSERT INTO FKTABLE VALUES (1, 3, 5);
|
|
INSERT INTO FKTABLE VALUES (2, 4, 8);
|
|
INSERT INTO FKTABLE VALUES (3, 6, 12);
|
|
INSERT INTO FKTABLE VALUES (NULL, NULL, 0);
|
|
-- Insert failed rows into FK TABLE
|
|
INSERT INTO FKTABLE VALUES (100, 2, 4);
|
|
ERROR: insert or update on table "fktable" violates foreign key constraint "constrname2"
|
|
DETAIL: Key (ftest1,ftest2)=(100,2) is not present in table "pktable".
|
|
INSERT INTO FKTABLE VALUES (2, 2, 4);
|
|
ERROR: insert or update on table "fktable" violates foreign key constraint "constrname2"
|
|
DETAIL: Key (ftest1,ftest2)=(2,2) is not present in table "pktable".
|
|
INSERT INTO FKTABLE VALUES (NULL, 2, 4);
|
|
ERROR: insert or update on table "fktable" violates foreign key constraint "constrname2"
|
|
DETAIL: MATCH FULL does not allow mixing of null and nonnull key values.
|
|
INSERT INTO FKTABLE VALUES (1, NULL, 4);
|
|
ERROR: insert or update on table "fktable" violates foreign key constraint "constrname2"
|
|
DETAIL: MATCH FULL does not allow mixing of null and nonnull key values.
|
|
-- Check FKTABLE
|
|
SELECT * FROM FKTABLE;
|
|
ftest1 | ftest2 | ftest3
|
|
--------+--------+--------
|
|
1 | 2 | 4
|
|
1 | 3 | 5
|
|
2 | 4 | 8
|
|
3 | 6 | 12
|
|
| | 0
|
|
(5 rows)
|
|
|
|
-- Delete a row from PK TABLE
|
|
DELETE FROM PKTABLE WHERE ptest1=1 and ptest2=2;
|
|
-- Check FKTABLE to check for removal
|
|
SELECT * FROM FKTABLE;
|
|
ftest1 | ftest2 | ftest3
|
|
--------+--------+--------
|
|
1 | 3 | 5
|
|
2 | 4 | 8
|
|
3 | 6 | 12
|
|
| | 0
|
|
-1 | -2 | 4
|
|
(5 rows)
|
|
|
|
-- Delete another row from PK TABLE
|
|
DELETE FROM PKTABLE WHERE ptest1=5 and ptest2=10;
|
|
-- Check FKTABLE (should be no change)
|
|
SELECT * FROM FKTABLE;
|
|
ftest1 | ftest2 | ftest3
|
|
--------+--------+--------
|
|
1 | 3 | 5
|
|
2 | 4 | 8
|
|
3 | 6 | 12
|
|
| | 0
|
|
-1 | -2 | 4
|
|
(5 rows)
|
|
|
|
-- Update a row from PK TABLE
|
|
UPDATE PKTABLE SET ptest1=1 WHERE ptest1=2;
|
|
-- Check FKTABLE for update of matched row
|
|
SELECT * FROM FKTABLE;
|
|
ftest1 | ftest2 | ftest3
|
|
--------+--------+--------
|
|
1 | 3 | 5
|
|
3 | 6 | 12
|
|
| | 0
|
|
-1 | -2 | 4
|
|
-1 | -2 | 8
|
|
(5 rows)
|
|
|
|
-- this should fail for lack of CASCADE
|
|
DROP TABLE PKTABLE;
|
|
NOTICE: constraint constrname2 on table fktable depends on table pktable
|
|
ERROR: cannot drop table pktable because other objects depend on it
|
|
HINT: Use DROP ... CASCADE to drop the dependent objects too.
|
|
DROP TABLE PKTABLE CASCADE;
|
|
NOTICE: drop cascades to constraint constrname2 on table fktable
|
|
DROP TABLE FKTABLE;
|
|
--
|
|
-- First test, check with no on delete or on update
|
|
--
|
|
CREATE TABLE PKTABLE ( ptest1 int PRIMARY KEY, ptest2 text );
|
|
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "pktable_pkey" for table "pktable"
|
|
CREATE TABLE FKTABLE ( ftest1 int REFERENCES PKTABLE MATCH FULL, ftest2 int );
|
|
NOTICE: CREATE TABLE will create implicit triggers for foreign-key checks
|
|
-- Insert test data into PKTABLE
|
|
INSERT INTO PKTABLE VALUES (1, 'Test1');
|
|
INSERT INTO PKTABLE VALUES (2, 'Test2');
|
|
INSERT INTO PKTABLE VALUES (3, 'Test3');
|
|
INSERT INTO PKTABLE VALUES (4, 'Test4');
|
|
INSERT INTO PKTABLE VALUES (5, 'Test5');
|
|
-- Insert successful rows into FK TABLE
|
|
INSERT INTO FKTABLE VALUES (1, 2);
|
|
INSERT INTO FKTABLE VALUES (2, 3);
|
|
INSERT INTO FKTABLE VALUES (3, 4);
|
|
INSERT INTO FKTABLE VALUES (NULL, 1);
|
|
-- Insert a failed row into FK TABLE
|
|
INSERT INTO FKTABLE VALUES (100, 2);
|
|
ERROR: insert or update on table "fktable" violates foreign key constraint "$1"
|
|
DETAIL: Key (ftest1)=(100) is not present in table "pktable".
|
|
-- Check FKTABLE
|
|
SELECT * FROM FKTABLE;
|
|
ftest1 | ftest2
|
|
--------+--------
|
|
1 | 2
|
|
2 | 3
|
|
3 | 4
|
|
| 1
|
|
(4 rows)
|
|
|
|
-- Check PKTABLE
|
|
SELECT * FROM PKTABLE;
|
|
ptest1 | ptest2
|
|
--------+--------
|
|
1 | Test1
|
|
2 | Test2
|
|
3 | Test3
|
|
4 | Test4
|
|
5 | Test5
|
|
(5 rows)
|
|
|
|
-- Delete a row from PK TABLE (should fail)
|
|
DELETE FROM PKTABLE WHERE ptest1=1;
|
|
ERROR: update or delete on "pktable" violates foreign key constraint "$1" on "fktable"
|
|
DETAIL: Key (ptest1)=(1) is still referenced from table "fktable".
|
|
-- Delete a row from PK TABLE (should succeed)
|
|
DELETE FROM PKTABLE WHERE ptest1=5;
|
|
-- Check PKTABLE for deletes
|
|
SELECT * FROM PKTABLE;
|
|
ptest1 | ptest2
|
|
--------+--------
|
|
1 | Test1
|
|
2 | Test2
|
|
3 | Test3
|
|
4 | Test4
|
|
(4 rows)
|
|
|
|
-- Update a row from PK TABLE (should fail)
|
|
UPDATE PKTABLE SET ptest1=0 WHERE ptest1=2;
|
|
ERROR: update or delete on "pktable" violates foreign key constraint "$1" on "fktable"
|
|
DETAIL: Key (ptest1)=(2) is still referenced from table "fktable".
|
|
-- Update a row from PK TABLE (should succeed)
|
|
UPDATE PKTABLE SET ptest1=0 WHERE ptest1=4;
|
|
-- Check PKTABLE for updates
|
|
SELECT * FROM PKTABLE;
|
|
ptest1 | ptest2
|
|
--------+--------
|
|
1 | Test1
|
|
2 | Test2
|
|
3 | Test3
|
|
0 | Test4
|
|
(4 rows)
|
|
|
|
DROP TABLE FKTABLE;
|
|
DROP TABLE PKTABLE;
|
|
-- MATCH unspecified
|
|
-- Base test restricting update/delete
|
|
CREATE TABLE PKTABLE ( ptest1 int, ptest2 int, ptest3 int, ptest4 text, PRIMARY KEY(ptest1, ptest2, ptest3) );
|
|
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "pktable_pkey" for table "pktable"
|
|
CREATE TABLE FKTABLE ( ftest1 int, ftest2 int, ftest3 int, ftest4 int, CONSTRAINT constrname3
|
|
FOREIGN KEY(ftest1, ftest2, ftest3) REFERENCES PKTABLE);
|
|
NOTICE: CREATE TABLE will create implicit triggers for foreign-key checks
|
|
-- Insert Primary Key values
|
|
INSERT 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 Foreign Key values
|
|
INSERT INTO FKTABLE VALUES (1, 2, 3, 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 values
|
|
INSERT INTO FKTABLE VALUES (1, 2, 7, 6);
|
|
ERROR: insert or update on table "fktable" violates foreign key constraint "constrname3"
|
|
DETAIL: Key (ftest1,ftest2,ftest3)=(1,2,7) is not present in table "pktable".
|
|
-- Show FKTABLE
|
|
SELECT * from FKTABLE;
|
|
ftest1 | ftest2 | ftest3 | ftest4
|
|
--------+--------+--------+--------
|
|
1 | 2 | 3 | 1
|
|
| 2 | 3 | 2
|
|
2 | | 3 | 3
|
|
| 2 | 7 | 4
|
|
| 3 | 4 | 5
|
|
(5 rows)
|
|
|
|
-- Try to update something that should fail
|
|
UPDATE PKTABLE set ptest2=5 where ptest2=2;
|
|
ERROR: update or delete on "pktable" violates foreign key constraint "constrname3" on "fktable"
|
|
DETAIL: Key (ptest1,ptest2,ptest3)=(1,2,3) is still referenced from table "fktable".
|
|
-- Try to update something that should succeed
|
|
UPDATE PKTABLE set ptest1=1 WHERE ptest2=3;
|
|
-- Try to delete something that should fail
|
|
DELETE FROM PKTABLE where ptest1=1 and ptest2=2 and ptest3=3;
|
|
ERROR: update or delete on "pktable" violates foreign key constraint "constrname3" on "fktable"
|
|
DETAIL: Key (ptest1,ptest2,ptest3)=(1,2,3) is still referenced from table "fktable".
|
|
-- Try to delete something that should work
|
|
DELETE FROM PKTABLE where ptest1=2;
|
|
-- Show PKTABLE and FKTABLE
|
|
SELECT * from PKTABLE;
|
|
ptest1 | ptest2 | ptest3 | ptest4
|
|
--------+--------+--------+--------
|
|
1 | 2 | 3 | test1
|
|
1 | 3 | 3 | test2
|
|
1 | 3 | 4 | test3
|
|
(3 rows)
|
|
|
|
SELECT * from FKTABLE;
|
|
ftest1 | ftest2 | ftest3 | ftest4
|
|
--------+--------+--------+--------
|
|
1 | 2 | 3 | 1
|
|
| 2 | 3 | 2
|
|
2 | | 3 | 3
|
|
| 2 | 7 | 4
|
|
| 3 | 4 | 5
|
|
(5 rows)
|
|
|
|
DROP TABLE FKTABLE;
|
|
DROP TABLE PKTABLE;
|
|
-- cascade update/delete
|
|
CREATE TABLE PKTABLE ( ptest1 int, ptest2 int, ptest3 int, ptest4 text, PRIMARY KEY(ptest1, ptest2, ptest3) );
|
|
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "pktable_pkey" for table "pktable"
|
|
CREATE TABLE FKTABLE ( ftest1 int, ftest2 int, ftest3 int, ftest4 int, CONSTRAINT constrname3
|
|
FOREIGN KEY(ftest1, ftest2, ftest3) REFERENCES PKTABLE
|
|
ON DELETE CASCADE ON UPDATE CASCADE);
|
|
NOTICE: CREATE TABLE will create implicit triggers for foreign-key checks
|
|
-- Insert Primary Key values
|
|
INSERT 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 Foreign Key values
|
|
INSERT INTO FKTABLE VALUES (1, 2, 3, 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 values
|
|
INSERT INTO FKTABLE VALUES (1, 2, 7, 6);
|
|
ERROR: insert or update on table "fktable" violates foreign key constraint "constrname3"
|
|
DETAIL: Key (ftest1,ftest2,ftest3)=(1,2,7) is not present in table "pktable".
|
|
-- Show FKTABLE
|
|
SELECT * from FKTABLE;
|
|
ftest1 | ftest2 | ftest3 | ftest4
|
|
--------+--------+--------+--------
|
|
1 | 2 | 3 | 1
|
|
| 2 | 3 | 2
|
|
2 | | 3 | 3
|
|
| 2 | 7 | 4
|
|
| 3 | 4 | 5
|
|
(5 rows)
|
|
|
|
-- Try to update something that will cascade
|
|
UPDATE PKTABLE set ptest2=5 where ptest2=2;
|
|
-- Try to update something that should not cascade
|
|
UPDATE PKTABLE set ptest1=1 WHERE ptest2=3;
|
|
-- Show PKTABLE and FKTABLE
|
|
SELECT * from PKTABLE;
|
|
ptest1 | ptest2 | ptest3 | ptest4
|
|
--------+--------+--------+--------
|
|
2 | 4 | 5 | test4
|
|
1 | 5 | 3 | test1
|
|
1 | 3 | 3 | test2
|
|
1 | 3 | 4 | test3
|
|
(4 rows)
|
|
|
|
SELECT * from FKTABLE;
|
|
ftest1 | ftest2 | ftest3 | ftest4
|
|
--------+--------+--------+--------
|
|
| 2 | 3 | 2
|
|
2 | | 3 | 3
|
|
| 2 | 7 | 4
|
|
| 3 | 4 | 5
|
|
1 | 5 | 3 | 1
|
|
(5 rows)
|
|
|
|
-- Try to delete something that should cascade
|
|
DELETE FROM PKTABLE where ptest1=1 and ptest2=5 and ptest3=3;
|
|
-- Show PKTABLE and FKTABLE
|
|
SELECT * from PKTABLE;
|
|
ptest1 | ptest2 | ptest3 | ptest4
|
|
--------+--------+--------+--------
|
|
2 | 4 | 5 | test4
|
|
1 | 3 | 3 | test2
|
|
1 | 3 | 4 | test3
|
|
(3 rows)
|
|
|
|
SELECT * from FKTABLE;
|
|
ftest1 | ftest2 | ftest3 | ftest4
|
|
--------+--------+--------+--------
|
|
| 2 | 3 | 2
|
|
2 | | 3 | 3
|
|
| 2 | 7 | 4
|
|
| 3 | 4 | 5
|
|
(4 rows)
|
|
|
|
-- Try to delete something that should not have a cascade
|
|
DELETE FROM PKTABLE where ptest1=2;
|
|
-- Show PKTABLE and FKTABLE
|
|
SELECT * from PKTABLE;
|
|
ptest1 | ptest2 | ptest3 | ptest4
|
|
--------+--------+--------+--------
|
|
1 | 3 | 3 | test2
|
|
1 | 3 | 4 | test3
|
|
(2 rows)
|
|
|
|
SELECT * from FKTABLE;
|
|
ftest1 | ftest2 | ftest3 | ftest4
|
|
--------+--------+--------+--------
|
|
| 2 | 3 | 2
|
|
2 | | 3 | 3
|
|
| 2 | 7 | 4
|
|
| 3 | 4 | 5
|
|
(4 rows)
|
|
|
|
DROP TABLE FKTABLE;
|
|
DROP TABLE PKTABLE;
|
|
-- set null update / set default delete
|
|
CREATE TABLE PKTABLE ( ptest1 int, ptest2 int, ptest3 int, ptest4 text, PRIMARY KEY(ptest1, ptest2, ptest3) );
|
|
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "pktable_pkey" for table "pktable"
|
|
CREATE TABLE FKTABLE ( ftest1 int DEFAULT 0, ftest2 int, ftest3 int, ftest4 int, CONSTRAINT constrname3
|
|
FOREIGN KEY(ftest1, ftest2, ftest3) REFERENCES PKTABLE
|
|
ON DELETE SET DEFAULT ON UPDATE SET NULL);
|
|
NOTICE: CREATE TABLE will create implicit triggers for foreign-key checks
|
|
-- Insert Primary Key values
|
|
INSERT 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 Foreign Key values
|
|
INSERT INTO FKTABLE VALUES (1, 2, 3, 1);
|
|
INSERT INTO FKTABLE VALUES (2, 3, 4, 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 values
|
|
INSERT INTO FKTABLE VALUES (1, 2, 7, 6);
|
|
ERROR: insert or update on table "fktable" violates foreign key constraint "constrname3"
|
|
DETAIL: Key (ftest1,ftest2,ftest3)=(1,2,7) is not present in table "pktable".
|
|
-- Show FKTABLE
|
|
SELECT * from FKTABLE;
|
|
ftest1 | ftest2 | ftest3 | ftest4
|
|
--------+--------+--------+--------
|
|
1 | 2 | 3 | 1
|
|
2 | 3 | 4 | 1
|
|
| 2 | 3 | 2
|
|
2 | | 3 | 3
|
|
| 2 | 7 | 4
|
|
| 3 | 4 | 5
|
|
(6 rows)
|
|
|
|
-- Try to update something that will set null
|
|
UPDATE PKTABLE set ptest2=5 where ptest2=2;
|
|
-- Try to update something that should not set null
|
|
UPDATE PKTABLE set ptest2=2 WHERE ptest2=3 and ptest1=1;
|
|
-- Show PKTABLE and FKTABLE
|
|
SELECT * from PKTABLE;
|
|
ptest1 | ptest2 | ptest3 | ptest4
|
|
--------+--------+--------+--------
|
|
2 | 3 | 4 | test3
|
|
2 | 4 | 5 | test4
|
|
1 | 5 | 3 | test1
|
|
1 | 2 | 3 | test2
|
|
(4 rows)
|
|
|
|
SELECT * from FKTABLE;
|
|
ftest1 | ftest2 | ftest3 | ftest4
|
|
--------+--------+--------+--------
|
|
2 | 3 | 4 | 1
|
|
| 2 | 3 | 2
|
|
2 | | 3 | 3
|
|
| 2 | 7 | 4
|
|
| 3 | 4 | 5
|
|
1 | | 3 | 1
|
|
(6 rows)
|
|
|
|
-- Try to delete something that should set default
|
|
DELETE FROM PKTABLE where ptest1=2 and ptest2=3 and ptest3=4;
|
|
-- Show PKTABLE and FKTABLE
|
|
SELECT * from PKTABLE;
|
|
ptest1 | ptest2 | ptest3 | ptest4
|
|
--------+--------+--------+--------
|
|
2 | 4 | 5 | test4
|
|
1 | 5 | 3 | test1
|
|
1 | 2 | 3 | test2
|
|
(3 rows)
|
|
|
|
SELECT * from FKTABLE;
|
|
ftest1 | ftest2 | ftest3 | ftest4
|
|
--------+--------+--------+--------
|
|
| 2 | 3 | 2
|
|
2 | | 3 | 3
|
|
| 2 | 7 | 4
|
|
| 3 | 4 | 5
|
|
1 | | 3 | 1
|
|
0 | | | 1
|
|
(6 rows)
|
|
|
|
-- Try to delete something that should not set default
|
|
DELETE FROM PKTABLE where ptest2=5;
|
|
-- Show PKTABLE and FKTABLE
|
|
SELECT * from PKTABLE;
|
|
ptest1 | ptest2 | ptest3 | ptest4
|
|
--------+--------+--------+--------
|
|
2 | 4 | 5 | test4
|
|
1 | 2 | 3 | test2
|
|
(2 rows)
|
|
|
|
SELECT * from FKTABLE;
|
|
ftest1 | ftest2 | ftest3 | ftest4
|
|
--------+--------+--------+--------
|
|
| 2 | 3 | 2
|
|
2 | | 3 | 3
|
|
| 2 | 7 | 4
|
|
| 3 | 4 | 5
|
|
1 | | 3 | 1
|
|
0 | | | 1
|
|
(6 rows)
|
|
|
|
DROP TABLE FKTABLE;
|
|
DROP TABLE PKTABLE;
|
|
-- set default update / set null delete
|
|
CREATE TABLE PKTABLE ( ptest1 int, ptest2 int, ptest3 int, ptest4 text, PRIMARY KEY(ptest1, ptest2, ptest3) );
|
|
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "pktable_pkey" for table "pktable"
|
|
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);
|
|
NOTICE: CREATE TABLE will create implicit triggers for foreign-key checks
|
|
-- Insert Primary Key values
|
|
INSERT 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 values
|
|
INSERT 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 values
|
|
INSERT INTO FKTABLE VALUES (1, 2, 7, 6);
|
|
ERROR: insert or update on table "fktable" violates foreign key constraint "constrname3"
|
|
DETAIL: Key (ftest1,ftest2,ftest3)=(1,2,7) is not present in table "pktable".
|
|
-- Show FKTABLE
|
|
SELECT * from FKTABLE;
|
|
ftest1 | ftest2 | ftest3 | ftest4
|
|
--------+--------+--------+--------
|
|
1 | 2 | 3 | 1
|
|
2 | 3 | 4 | 1
|
|
2 | 4 | 5 | 1
|
|
| 2 | 3 | 2
|
|
2 | | 3 | 3
|
|
| 2 | 7 | 4
|
|
| 3 | 4 | 5
|
|
(7 rows)
|
|
|
|
-- Try to update something that will fail
|
|
UPDATE PKTABLE set ptest2=5 where ptest2=2;
|
|
ERROR: insert or update on table "fktable" violates foreign key constraint "constrname3"
|
|
DETAIL: Key (ftest1,ftest2,ftest3)=(1,-1,3) is not present in table "pktable".
|
|
-- Try to update something that will set default
|
|
UPDATE 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 default
|
|
UPDATE PKTABLE set ptest2=2 WHERE ptest2=3 and ptest1=1;
|
|
-- Show PKTABLE and FKTABLE
|
|
SELECT * from PKTABLE;
|
|
ptest1 | ptest2 | ptest3 | ptest4
|
|
--------+--------+--------+--------
|
|
2 | 3 | 4 | test3
|
|
2 | -1 | 5 | test5
|
|
0 | 5 | 10 | test1
|
|
2 | 10 | 5 | test4
|
|
1 | 2 | 3 | test2
|
|
(5 rows)
|
|
|
|
SELECT * from FKTABLE;
|
|
ftest1 | ftest2 | ftest3 | ftest4
|
|
--------+--------+--------+--------
|
|
2 | 3 | 4 | 1
|
|
| 2 | 3 | 2
|
|
2 | | 3 | 3
|
|
| 2 | 7 | 4
|
|
| 3 | 4 | 5
|
|
0 | -1 | | 1
|
|
2 | -1 | 5 | 1
|
|
(7 rows)
|
|
|
|
-- Try to delete something that should set null
|
|
DELETE FROM PKTABLE where ptest1=2 and ptest2=3 and ptest3=4;
|
|
-- Show PKTABLE and FKTABLE
|
|
SELECT * from PKTABLE;
|
|
ptest1 | ptest2 | ptest3 | ptest4
|
|
--------+--------+--------+--------
|
|
2 | -1 | 5 | test5
|
|
0 | 5 | 10 | test1
|
|
2 | 10 | 5 | test4
|
|
1 | 2 | 3 | test2
|
|
(4 rows)
|
|
|
|
SELECT * from FKTABLE;
|
|
ftest1 | ftest2 | ftest3 | ftest4
|
|
--------+--------+--------+--------
|
|
| 2 | 3 | 2
|
|
2 | | 3 | 3
|
|
| 2 | 7 | 4
|
|
| 3 | 4 | 5
|
|
0 | -1 | | 1
|
|
2 | -1 | 5 | 1
|
|
| | | 1
|
|
(7 rows)
|
|
|
|
-- Try to delete something that should not set null
|
|
DELETE FROM PKTABLE where ptest2=5;
|
|
-- Show PKTABLE and FKTABLE
|
|
SELECT * from PKTABLE;
|
|
ptest1 | ptest2 | ptest3 | ptest4
|
|
--------+--------+--------+--------
|
|
2 | -1 | 5 | test5
|
|
2 | 10 | 5 | test4
|
|
1 | 2 | 3 | test2
|
|
(3 rows)
|
|
|
|
SELECT * from FKTABLE;
|
|
ftest1 | ftest2 | ftest3 | ftest4
|
|
--------+--------+--------+--------
|
|
| 2 | 3 | 2
|
|
2 | | 3 | 3
|
|
| 2 | 7 | 4
|
|
| 3 | 4 | 5
|
|
0 | -1 | | 1
|
|
2 | -1 | 5 | 1
|
|
| | | 1
|
|
(7 rows)
|
|
|
|
DROP TABLE FKTABLE;
|
|
DROP TABLE PKTABLE;
|
|
CREATE TABLE PKTABLE (ptest1 int PRIMARY KEY);
|
|
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "pktable_pkey" for table "pktable"
|
|
CREATE TABLE FKTABLE_FAIL1 ( ftest1 int, CONSTRAINT fkfail1 FOREIGN KEY (ftest2) REFERENCES PKTABLE);
|
|
NOTICE: CREATE TABLE will create implicit triggers for foreign-key checks
|
|
ERROR: column "ftest2" referenced in foreign key constraint does not exist
|
|
CREATE TABLE FKTABLE_FAIL2 ( ftest1 int, CONSTRAINT fkfail1 FOREIGN KEY (ftest1) REFERENCES PKTABLE(ptest2));
|
|
NOTICE: CREATE TABLE will create implicit triggers for foreign-key checks
|
|
ERROR: column "ptest2" referenced in foreign key constraint does not exist
|
|
DROP TABLE FKTABLE_FAIL1;
|
|
ERROR: table "fktable_fail1" does not exist
|
|
DROP TABLE FKTABLE_FAIL2;
|
|
ERROR: table "fktable_fail2" does not exist
|
|
DROP TABLE PKTABLE;
|
|
-- Test for referencing column number smaller than referenced constraint
|
|
CREATE TABLE PKTABLE (ptest1 int, ptest2 int, UNIQUE(ptest1, ptest2));
|
|
NOTICE: CREATE TABLE / UNIQUE will create implicit index "pktable_ptest1_key" for table "pktable"
|
|
CREATE TABLE FKTABLE_FAIL1 (ftest1 int REFERENCES pktable(ptest1));
|
|
NOTICE: CREATE TABLE will create implicit triggers for foreign-key checks
|
|
ERROR: there is no unique constraint matching given keys for referenced table "pktable"
|
|
DROP TABLE FKTABLE_FAIL1;
|
|
ERROR: table "fktable_fail1" does not exist
|
|
DROP TABLE PKTABLE;
|
|
--
|
|
-- Tests for mismatched types
|
|
--
|
|
-- Basic one column, two table setup
|
|
CREATE TABLE PKTABLE (ptest1 int PRIMARY KEY);
|
|
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "pktable_pkey" for table "pktable"
|
|
-- This next should fail, because inet=int does not exist
|
|
CREATE TABLE FKTABLE (ftest1 inet REFERENCES pktable);
|
|
NOTICE: CREATE TABLE will create implicit triggers for foreign-key checks
|
|
ERROR: operator does not exist: inet = integer
|
|
HINT: No operator matches the given name and argument type(s). You may need to add explicit type casts.
|
|
-- This should also fail for the same reason, but here we
|
|
-- give the column name
|
|
CREATE TABLE FKTABLE (ftest1 inet REFERENCES pktable(ptest1));
|
|
NOTICE: CREATE TABLE will create implicit triggers for foreign-key checks
|
|
ERROR: operator does not exist: inet = integer
|
|
HINT: No operator matches the given name and argument type(s). You may need to add explicit type casts.
|
|
-- This should succeed, even though they are different types
|
|
-- because varchar=int does exist
|
|
CREATE TABLE FKTABLE (ftest1 varchar REFERENCES pktable);
|
|
NOTICE: CREATE TABLE will create implicit triggers for foreign-key checks
|
|
DROP TABLE FKTABLE;
|
|
-- As should this
|
|
CREATE TABLE FKTABLE (ftest1 varchar REFERENCES pktable(ptest1));
|
|
NOTICE: CREATE TABLE will create implicit triggers for foreign-key checks
|
|
DROP TABLE FKTABLE;
|
|
DROP TABLE PKTABLE;
|
|
-- Two columns, two tables
|
|
CREATE TABLE PKTABLE (ptest1 int, ptest2 inet, PRIMARY KEY(ptest1, ptest2));
|
|
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "pktable_pkey" for table "pktable"
|
|
-- This should fail, because we just chose really odd types
|
|
CREATE TABLE FKTABLE (ftest1 cidr, ftest2 timestamp, FOREIGN KEY(ftest1, ftest2) REFERENCES pktable);
|
|
NOTICE: CREATE TABLE will create implicit triggers for foreign-key checks
|
|
ERROR: operator does not exist: cidr = integer
|
|
HINT: No operator matches the given name and argument type(s). You may need to add explicit type casts.
|
|
-- Again, so should this...
|
|
CREATE TABLE FKTABLE (ftest1 cidr, ftest2 timestamp, FOREIGN KEY(ftest1, ftest2) REFERENCES pktable(ptest1, ptest2));
|
|
NOTICE: CREATE TABLE will create implicit triggers for foreign-key checks
|
|
ERROR: operator does not exist: cidr = integer
|
|
HINT: No operator matches the given name and argument type(s). You may need to add explicit type casts.
|
|
-- This fails because we mixed up the column ordering
|
|
CREATE TABLE FKTABLE (ftest1 int, ftest2 inet, FOREIGN KEY(ftest2, ftest1) REFERENCES pktable);
|
|
NOTICE: CREATE TABLE will create implicit triggers for foreign-key checks
|
|
ERROR: operator does not exist: inet = integer
|
|
HINT: No operator matches the given name and argument type(s). You may need to add explicit type casts.
|
|
-- As does this...
|
|
CREATE TABLE FKTABLE (ftest1 int, ftest2 inet, FOREIGN KEY(ftest2, ftest1) REFERENCES pktable(ptest1, ptest2));
|
|
NOTICE: CREATE TABLE will create implicit triggers for foreign-key checks
|
|
ERROR: operator does not exist: inet = integer
|
|
HINT: No operator matches the given name and argument type(s). You may need to add explicit type casts.
|
|
-- And again..
|
|
CREATE TABLE FKTABLE (ftest1 int, ftest2 inet, FOREIGN KEY(ftest1, ftest2) REFERENCES pktable(ptest2, ptest1));
|
|
NOTICE: CREATE TABLE will create implicit triggers for foreign-key checks
|
|
ERROR: operator does not exist: integer = inet
|
|
HINT: No operator matches the given name and argument type(s). You may need to add explicit type casts.
|
|
-- This works...
|
|
CREATE TABLE FKTABLE (ftest1 int, ftest2 inet, FOREIGN KEY(ftest2, ftest1) REFERENCES pktable(ptest2, ptest1));
|
|
NOTICE: CREATE TABLE will create implicit triggers for foreign-key checks
|
|
DROP TABLE FKTABLE;
|
|
-- As does this
|
|
CREATE TABLE FKTABLE (ftest1 int, ftest2 inet, FOREIGN KEY(ftest1, ftest2) REFERENCES pktable(ptest1, ptest2));
|
|
NOTICE: CREATE TABLE will create implicit triggers for foreign-key checks
|
|
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));
|
|
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "pktable_pkey" for table "pktable"
|
|
NOTICE: CREATE TABLE will create implicit triggers for foreign-key checks
|
|
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);
|
|
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "pktable_pkey" for table "pktable"
|
|
NOTICE: CREATE TABLE will create implicit triggers for foreign-key checks
|
|
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));
|
|
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "pktable_pkey" for table "pktable"
|
|
NOTICE: CREATE TABLE will create implicit triggers for foreign-key checks
|
|
ERROR: operator does not exist: integer = inet
|
|
HINT: No operator matches the given name and argument type(s). You may need to add explicit type casts.
|
|
-- Nor should this... (same reason, we have 4,3 referencing 1,2 which mismatches types
|
|
CREATE TABLE PKTABLE (ptest1 int, ptest2 inet, ptest3 int, ptest4 inet, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest4,
|
|
ptest3) REFERENCES pktable(ptest1, ptest2));
|
|
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "pktable_pkey" for table "pktable"
|
|
NOTICE: CREATE TABLE will create implicit triggers for foreign-key checks
|
|
ERROR: operator does not exist: inet = integer
|
|
HINT: No operator matches the given name and argument type(s). You may need to add explicit type casts.
|
|
-- 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);
|
|
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "pktable_pkey" for table "pktable"
|
|
NOTICE: CREATE TABLE will create implicit triggers for foreign-key checks
|
|
ERROR: operator does not exist: inet = integer
|
|
HINT: No operator matches the given name and argument type(s). You may need to add explicit type casts.
|
|
--
|
|
-- 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);
|
|
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "pktable_pkey" for table "pktable"
|
|
NOTICE: CREATE TABLE / UNIQUE will create implicit index "pktable_base1_key" for table "pktable"
|
|
create table fktable (ftest1 int references pktable(base1));
|
|
NOTICE: CREATE TABLE will create implicit triggers for foreign-key checks
|
|
-- now some ins, upd, del
|
|
insert into pktable(base1) values (1);
|
|
insert into pktable(base1) values (2);
|
|
-- let's insert a non-existant fktable value
|
|
insert into fktable(ftest1) values (3);
|
|
ERROR: insert or update on table "fktable" violates foreign key constraint "$1"
|
|
DETAIL: Key (ftest1)=(3) is not present in table "pktable".
|
|
-- let's make a valid row for that
|
|
insert into pktable(base1) values (3);
|
|
insert into fktable(ftest1) values (3);
|
|
-- let's try removing a row that should fail from pktable
|
|
delete from pktable where base1>2;
|
|
ERROR: update or delete on "pktable" violates foreign key constraint "$1" on "fktable"
|
|
DETAIL: Key (base1)=(3) is still referenced from table "fktable".
|
|
-- okay, let's try updating all of the base1 values to *4
|
|
-- which should fail.
|
|
update pktable set base1=base1*4;
|
|
ERROR: update or delete on "pktable" violates foreign key constraint "$1" on "fktable"
|
|
DETAIL: Key (base1)=(3) is still referenced from table "fktable".
|
|
-- okay, let's try an update that should work.
|
|
update pktable set base1=base1*4 where base1<3;
|
|
-- and a delete that should work
|
|
delete from pktable where base1>3;
|
|
-- cleanup
|
|
drop table fktable;
|
|
delete from pktable;
|
|
-- Now 2 columns 2 tables, matching types
|
|
create table fktable (ftest1 int, ftest2 int, foreign key(ftest1, ftest2) references pktable(base1, ptest1));
|
|
NOTICE: CREATE TABLE will create implicit triggers for foreign-key checks
|
|
-- now some ins, upd, del
|
|
insert into pktable(base1, ptest1) values (1, 1);
|
|
insert into pktable(base1, ptest1) values (2, 2);
|
|
-- let's insert a non-existant fktable value
|
|
insert into fktable(ftest1, ftest2) values (3, 1);
|
|
ERROR: insert or update on table "fktable" violates foreign key constraint "$1"
|
|
DETAIL: Key (ftest1,ftest2)=(3,1) is not present in table "pktable".
|
|
-- let's make a valid row for that
|
|
insert 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 pktable
|
|
delete from pktable where base1>2;
|
|
ERROR: update or delete on "pktable" violates foreign key constraint "$1" on "fktable"
|
|
DETAIL: Key (base1,ptest1)=(3,1) is still referenced from table "fktable".
|
|
-- okay, let's try updating all of the base1 values to *4
|
|
-- which should fail.
|
|
update pktable set base1=base1*4;
|
|
ERROR: update or delete on "pktable" violates foreign key constraint "$1" on "fktable"
|
|
DETAIL: Key (base1,ptest1)=(3,1) is still referenced from table "fktable".
|
|
-- okay, let's try an update that should work.
|
|
update pktable set base1=base1*4 where base1<3;
|
|
-- and a delete that should work
|
|
delete from pktable where base1>3;
|
|
-- cleanup
|
|
drop table fktable;
|
|
drop table pktable;
|
|
drop table pktable_base;
|
|
-- Now we'll do one all in 1 table with 2 columns of matching types
|
|
create 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);
|
|
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "pktable_pkey" for table "pktable"
|
|
NOTICE: CREATE TABLE will create implicit triggers for foreign-key checks
|
|
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, ptest1
|
|
insert into pktable (base1, ptest1, base2, ptest2) values (2, 3, 3, 2);
|
|
ERROR: insert or update on table "pktable" violates foreign key constraint "$1"
|
|
DETAIL: Key (base2,ptest2)=(3,2) is not present in table "pktable".
|
|
-- fails (2,2) is being referenced
|
|
delete from pktable where base1=2;
|
|
ERROR: update or delete on "pktable" violates foreign key constraint "$1" on "pktable"
|
|
DETAIL: Key (base1,ptest1)=(2,2) is still referenced from table "pktable".
|
|
-- fails (1,1) is being referenced (twice)
|
|
update pktable set base1=3 where base1=1;
|
|
ERROR: update or delete on "pktable" violates foreign key constraint "$1" on "pktable"
|
|
DETAIL: Key (base1,ptest1)=(1,1) is still referenced from table "pktable".
|
|
-- this sequence of two deletes will work, since after the first there will be no (2,*) references
|
|
delete from pktable where base2=2;
|
|
delete from pktable where base1=2;
|
|
drop table pktable;
|
|
drop table pktable_base;
|
|
-- 2 columns (2 tables), mismatched types
|
|
create table pktable_base(base1 int not null);
|
|
create table pktable(ptest1 inet, primary key(base1, ptest1)) inherits (pktable_base);
|
|
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "pktable_pkey" for table "pktable"
|
|
-- 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);
|
|
NOTICE: CREATE TABLE will create implicit triggers for foreign-key checks
|
|
ERROR: operator does not exist: cidr = integer
|
|
HINT: No operator matches the given name and argument type(s). You may need to add explicit type casts.
|
|
create table fktable(ftest1 cidr, ftest2 int[], foreign key (ftest1, ftest2) references pktable(base1, ptest1));
|
|
NOTICE: CREATE TABLE will create implicit triggers for foreign-key checks
|
|
ERROR: operator does not exist: cidr = integer
|
|
HINT: No operator matches the given name and argument type(s). You may need to add explicit type casts.
|
|
-- let's mix up which columns reference which
|
|
create table fktable(ftest1 int, ftest2 inet, foreign key(ftest2, ftest1) references pktable);
|
|
NOTICE: CREATE TABLE will create implicit triggers for foreign-key checks
|
|
ERROR: operator does not exist: inet = integer
|
|
HINT: No operator matches the given name and argument type(s). You may need to add explicit type casts.
|
|
create table fktable(ftest1 int, ftest2 inet, foreign key(ftest2, ftest1) references pktable(base1, ptest1));
|
|
NOTICE: CREATE TABLE will create implicit triggers for foreign-key checks
|
|
ERROR: operator does not exist: inet = integer
|
|
HINT: No operator matches the given name and argument type(s). You may need to add explicit type casts.
|
|
create table fktable(ftest1 int, ftest2 inet, foreign key(ftest1, ftest2) references pktable(ptest1, base1));
|
|
NOTICE: CREATE TABLE will create implicit triggers for foreign-key checks
|
|
ERROR: operator does not exist: integer = inet
|
|
HINT: No operator matches the given name and argument type(s). You may need to add explicit type casts.
|
|
drop table pktable;
|
|
drop table pktable_base;
|
|
-- 2 columns (1 table), mismatched types
|
|
create 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);
|
|
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "pktable_pkey" for table "pktable"
|
|
NOTICE: CREATE TABLE will create implicit triggers for foreign-key checks
|
|
ERROR: operator does not exist: inet[] = inet
|
|
HINT: No operator matches the given name and argument type(s). You may need to add explicit type casts.
|
|
create table pktable(ptest1 inet, ptest2 inet, primary key(base1, ptest1), foreign key(base2, ptest2) references
|
|
pktable(ptest1, base1)) inherits (pktable_base);
|
|
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "pktable_pkey" for table "pktable"
|
|
NOTICE: CREATE TABLE will create implicit triggers for foreign-key checks
|
|
ERROR: operator does not exist: integer = inet
|
|
HINT: No operator matches the given name and argument type(s). You may need to add explicit type casts.
|
|
create table pktable(ptest1 inet, ptest2 inet, primary key(base1, ptest1), foreign key(ptest2, base2) references
|
|
pktable(base1, ptest1)) inherits (pktable_base);
|
|
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "pktable_pkey" for table "pktable"
|
|
NOTICE: CREATE TABLE will create implicit triggers for foreign-key checks
|
|
ERROR: operator does not exist: inet = integer
|
|
HINT: No operator matches the given name and argument type(s). You may need to add explicit type casts.
|
|
create table pktable(ptest1 inet, ptest2 inet, primary key(base1, ptest1), foreign key(ptest2, base2) references
|
|
pktable(base1, ptest1)) inherits (pktable_base);
|
|
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "pktable_pkey" for table "pktable"
|
|
NOTICE: CREATE TABLE will create implicit triggers for foreign-key checks
|
|
ERROR: operator does not exist: inet = integer
|
|
HINT: No operator matches the given name and argument type(s). You may need to add explicit type casts.
|
|
drop table pktable;
|
|
ERROR: table "pktable" does not exist
|
|
drop table pktable_base;
|
|
--
|
|
-- Deferrable constraints
|
|
-- (right now, only FOREIGN KEY constraints can be deferred)
|
|
--
|
|
-- deferrable, explicitely deferred
|
|
CREATE TABLE pktable (
|
|
id INT4 PRIMARY KEY,
|
|
other INT4
|
|
);
|
|
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "pktable_pkey" for table "pktable"
|
|
CREATE TABLE fktable (
|
|
id INT4 PRIMARY KEY,
|
|
fk INT4 REFERENCES pktable DEFERRABLE
|
|
);
|
|
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "fktable_pkey" for table "fktable"
|
|
NOTICE: CREATE TABLE will create implicit triggers for foreign-key checks
|
|
-- default to immediate: should fail
|
|
INSERT INTO fktable VALUES (5, 10);
|
|
ERROR: insert or update on table "fktable" violates foreign key constraint "$1"
|
|
DETAIL: Key (fk)=(10) is not present in table "pktable".
|
|
-- explicitely defer the constraint
|
|
BEGIN;
|
|
SET CONSTRAINTS ALL DEFERRED;
|
|
INSERT INTO fktable VALUES (10, 15);
|
|
INSERT INTO pktable VALUES (15, 0); -- make the FK insert valid
|
|
COMMIT;
|
|
DROP TABLE fktable, pktable;
|
|
-- deferrable, initially deferred
|
|
CREATE TABLE pktable (
|
|
id INT4 PRIMARY KEY,
|
|
other INT4
|
|
);
|
|
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "pktable_pkey" for table "pktable"
|
|
CREATE TABLE fktable (
|
|
id INT4 PRIMARY KEY,
|
|
fk INT4 REFERENCES pktable DEFERRABLE INITIALLY DEFERRED
|
|
);
|
|
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "fktable_pkey" for table "fktable"
|
|
NOTICE: CREATE TABLE will create implicit triggers for foreign-key checks
|
|
-- default to deferred, should succeed
|
|
BEGIN;
|
|
INSERT INTO fktable VALUES (100, 200);
|
|
INSERT INTO pktable VALUES (200, 500); -- make the FK insert valid
|
|
COMMIT;
|
|
-- default to deferred, explicitely make immediate
|
|
BEGIN;
|
|
SET CONSTRAINTS ALL IMMEDIATE;
|
|
-- should fail
|
|
INSERT INTO fktable VALUES (500, 1000);
|
|
ERROR: insert or update on table "fktable" violates foreign key constraint "$1"
|
|
DETAIL: Key (fk)=(1000) is not present in table "pktable".
|
|
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
|
|
);
|
|
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "pktable_pkey" for table "pktable"
|
|
CREATE TABLE fktable (
|
|
id INT4 PRIMARY KEY,
|
|
fk INT4 REFERENCES pktable DEFERRABLE
|
|
);
|
|
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "fktable_pkey" for table "fktable"
|
|
NOTICE: CREATE TABLE will create implicit triggers for foreign-key checks
|
|
BEGIN;
|
|
SET CONSTRAINTS ALL DEFERRED;
|
|
-- should succeed, for now
|
|
INSERT INTO fktable VALUES (1000, 2000);
|
|
-- should cause transaction abort, due to preceding error
|
|
SET CONSTRAINTS ALL IMMEDIATE;
|
|
ERROR: insert or update on table "fktable" violates foreign key constraint "$1"
|
|
DETAIL: Key (fk)=(2000) is not present in table "pktable".
|
|
INSERT INTO pktable VALUES (2000, 3); -- too late
|
|
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
|
COMMIT;
|
|
DROP TABLE fktable, pktable;
|
|
-- deferrable, initially deferred
|
|
CREATE TABLE pktable (
|
|
id INT4 PRIMARY KEY,
|
|
other INT4
|
|
);
|
|
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "pktable_pkey" for table "pktable"
|
|
CREATE TABLE fktable (
|
|
id INT4 PRIMARY KEY,
|
|
fk INT4 REFERENCES pktable DEFERRABLE INITIALLY DEFERRED
|
|
);
|
|
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "fktable_pkey" for table "fktable"
|
|
NOTICE: CREATE TABLE will create implicit triggers for foreign-key checks
|
|
BEGIN;
|
|
-- no error here
|
|
INSERT INTO fktable VALUES (100, 200);
|
|
-- error here on commit
|
|
COMMIT;
|
|
ERROR: insert or update on table "fktable" violates foreign key constraint "$1"
|
|
DETAIL: Key (fk)=(200) is not present in table "pktable".
|