views:

61

answers:

2

Hi everyone,

I've created some tables in postgres, added a foreign key from one table to another and set ON DELETE to CASCADE. Strangely enough, I have some fields that appear to be violating this constraint.

Is this normal behaviour? And if so, is there a way to get the behaviour I want (no violations possible)?

Edit:

I orginaly created the foreign key as part of CREATE TABLE, just using

... REFERENCES product (id) ON UPDATE CASCADE ON DELETE CASCADE

The current code pgAdmin3 gives is

ALTER TABLE cultivar
  ADD CONSTRAINT cultivar_id_fkey FOREIGN KEY (id)
      REFERENCES product (id) MATCH SIMPLE
      ON UPDATE CASCADE ON DELETE CASCADE;

Edit 2:

To Clarify, I have a sneaking suspicion that the constraints are only checked when updates/inserts happen but are then never looked at again. Unfortunately I don't know enough about postgres to find out if this is true or how fields could end up in the database without those checks being run.

If this is the case, is there some way to check all the foreign keys and fix those problems?

A: 
Michael Clerx
There was never a real constraint violation.
Unreason
I realised I handled this situation a little strangely, so I made the extra effort and replicated the situation that caused my initial problems.
Michael Clerx
+1  A: 

I tried to create a simple example that shows foreign key constraint being enforced. With this example I prove am not allowed to enter data that violates the fk and I prove that if the fk is not in place during insert and I enable the fk that the fk constraint throws and error telling me data violates the fk. So I'm not seeing how you have data in table that violates a fk that is in place. I'm on 9.0, but this should not be different on 8.3. If you could show and working example that proves your issue that might help.

--CREATE TABLES--
CREATE TABLE parent
(
  parent_id integer NOT NULL,
  first_name character varying(50) NOT NULL,
  CONSTRAINT pk_parent PRIMARY KEY (parent_id)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE parent OWNER TO postgres;

CREATE TABLE child
(
  child_id integer NOT NULL,
  parent_id integer NOT NULL,
  first_name character varying(50) NOT NULL,
  CONSTRAINT pk_child PRIMARY KEY (child_id),
  CONSTRAINT fk1_child FOREIGN KEY (parent_id)
      REFERENCES parent (parent_id) MATCH SIMPLE
      ON UPDATE CASCADE ON DELETE CASCADE
)
WITH (
  OIDS=FALSE
);
ALTER TABLE child OWNER TO postgres;
--CREATE TABLES--

--INSERT TEST DATA--
INSERT INTO parent(parent_id,first_name)
SELECT 1,'Daddy'
UNION 
SELECT 2,'Mommy';

INSERT INTO child(child_id,parent_id,first_name)
SELECT 1,1,'Billy'
UNION 
SELECT 2,1,'Jenny'
UNION 
SELECT 3,1,'Kimmy'
UNION 
SELECT 4,2,'Billy'
UNION 
SELECT 5,2,'Jenny'
UNION 
SELECT 6,2,'Kimmy';
--INSERT TEST DATA--

--SHOW THE DATA WE HAVE--
select parent.first_name,
       child.first_name
from parent
inner join child
        on child.parent_id = parent.parent_id
order by parent.first_name, child.first_name asc;
--SHOW THE DATA WE HAVE--

--DELETE PARENT WHO HAS CHILDREN--
BEGIN TRANSACTION;
delete from parent
where parent_id = 1;

--Check to see if any children that were linked to Daddy are still there?
--None there so the cascade delete worked.
select parent.first_name,
       child.first_name
from parent
right outer join child
        on child.parent_id = parent.parent_id
order by parent.first_name, child.first_name asc;
ROLLBACK TRANSACTION;


--TRY ALLOW NO REFERENTIAL DATA IN--
BEGIN TRANSACTION;

--Get rid of fk constraint so we can insert red headed step child
ALTER TABLE child DROP CONSTRAINT fk1_child;

INSERT INTO child(child_id,parent_id,first_name)
SELECT 7,99999,'Red Headed Step Child';

select parent.first_name,
       child.first_name
from parent
right outer join child
        on child.parent_id = parent.parent_id
order by parent.first_name, child.first_name asc;

--Will throw FK check violation because parent 99999 doesn't exist in parent table
ALTER TABLE child
  ADD CONSTRAINT fk1_child FOREIGN KEY (parent_id)
      REFERENCES parent (parent_id) MATCH SIMPLE
      ON UPDATE CASCADE ON DELETE CASCADE;

ROLLBACK TRANSACTION;
--TRY ALLOW NO REFERENTIAL DATA IN--

--DROP TABLE parent;
--DROP TABLE child;
StarShip3000
Thanks for trying!
Michael Clerx