Reputation: 171
To create table I use:
CREATE TABLE category
(
cat_id serial NOT NULL,
cat_name character varying NOT NULL,
parent_id integer NOT NULL,
CONSTRAINT cat_id PRIMARY KEY (cat_id)
)
WITH (
OIDS=FALSE
);
ALTER TABLE category
OWNER TO pgsql;
parent_id is a id to another category. Now I have a problem: how to cascade delete record with its children? I need to set parent_id as foreign key to cat_id. I try this:
ALTER TABLE category
ADD CONSTRAINT cat_cat_id_fkey FOREIGN KEY (parent_id)
REFERENCES category (cat_id) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE CASCADE
But it falls with:
ERROR: insert or update on table "category" violates foreign key constraint "cat_cat_id_fkey"
DETAIL: Key (parent_id)=(0) is not present in table "category".
Upvotes: 5
Views: 22496
Reputation: 151
This is quite simple.
Here the foreign key parent_id
refers to cat_id
.
Here a record with parent_id=0
exists but not a record with cat_id=0
.
Upvotes: 1
Reputation: 44250
-- create some fake data for testing
--
DROP SCHEMA tmp CASCADE;
CREATE SCHEMA tmp ;
SET search_path=tmp;
CREATE TABLE category
(
cat_id serial NOT NULL,
cat_name character varying NOT NULL,
parent_id integer NOT NULL,
CONSTRAINT cat_id PRIMARY KEY (cat_id)
);
INSERT INTO category(cat_name,parent_id)
SELECT 'Name_' || gs::text
, gs % 3
FROM generate_series(0,9) gs
;
-- find the records with the non-existing parents
SELECT ca.parent_id , COUNT(*)
FROM category ca
WHERE NOT EXISTS (
SELECT *
FROM category nx
WHERE nx.cat_id = ca.parent_id
)
GROUP BY ca.parent_id
;
-- if all is well: proceed
-- make parent pointer nullable
ALTER TABLE category
ALTER COLUMN parent_id DROP NOT NULL
;
-- set non-existing parent pointers to NULL
UPDATE category ca
SET parent_id = NULL
WHERE NOT EXISTS (
SELECT *
FROM category nx
WHERE nx.cat_id = ca.parent_id
)
;
-- Finally, add the FK constraint
ALTER TABLE category
ADD CONSTRAINT cat_cat_id_fkey FOREIGN KEY (parent_id)
REFERENCES category (cat_id) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE CASCADE
;
Upvotes: 3
Reputation: 28641
The problem you have - what would be the parent_id
of a category at the top of the hierarchy?
If it will be null
- it will break the NOT NULL
constratint.
If it will be some arbitrary number like 0
- it will break the foreign key (like in your example).
The common solution - drop the NOT NULL
constratint on the parent_id
and set parent_id
to null
for top categories.
Upvotes: 6