Par rupteur le 14/08/2008 - 16:29
Bonjour,
je suis actuellement en train de tester le partitionnement de table,
et je me retrouve confronté à un problème de contrainte de clef étrangère
j'ai défini 4 table filles qui héritent d'une table mère (reference_test).
j'ai posé un trigger qui défini où doivent être insérées/modifiées/effacées les données.
j'ai aussi une table résultat qui possède une clef primaire étrangère (celle de la table mère)
lorsque j'insère les données dans la table mère, celles-ci sont bien diffusées où il faut.
INSERT INTO reference_test (clef_etr1,clef_etr2,clef_etr3,clef_etr4,ref_datetest,ref_pos1,ref_pos2,anadef_clef,typana_clef) VALUES (1,0,0,0,NOW(),50,1,1,1);
INSERT INTO reference_test (clef_etr1,clef_etr2,clef_etr3,clef_etr4,ref_datetest,ref_pos1,ref_pos2,anadef_clef,typana_clef) VALUES (0,1,0,0,NOW(),100,25,1,1);
mais si je tente une insertion dans la table resultat,
INSERT INTO resultat(ref_clef,res_plaque) VALUES(2,1);
j'obtient le message d'erreur suivant :
ERREUR: Une instruction insert ou update sur la table « resultat » viole la contrainte de clé étrangère « ref1 »
DETAIL: La clé (ref_clef)=(2) n'est pas présente dans la table « reference_test ».
Peut-être que je ne gère pas le partitionnement comme il le faudrait.
Merci d'avance pour vos éclaircissements.
Eric
ci-joint mon code pour plus de clarté.
CREATE TABLE reference_test
(
ref_clef bigserial NOT NULL,
clef_etr1 bigint,
clef_etr2 bigint,
clef_etr3 bigint,
clef_etr4 bigint,
ref_datetest date NOT NULL,
ref_pos1 numeric(4) NOT NULL,
ref_pos2 numeric(2) NOT NULL,
anadef_clef integer NOT NULL,
typana_clef integer NOT NULL,
PRIMARY KEY (ref_clef)
);
CREATE TABLE resultat
(
ref_clef bigint NOT NULL,
res_plaque numeric(4) DEFAULT 0 NOT NULL,
PRIMARY KEY (ref_clef)
);
ALTER TABLE resultat ADD CONSTRAINT ref1
FOREIGN KEY ( ref_clef )
REFERENCES reference_test ( ref_clef )
NOT DEFERRABLE;
CREATE TABLE reftest_cl
( CHECK (clef_etr1 IS NOT NULL AND clef_etr1>0::bigint))
INHERITS (reference_test);
CREATE TABLE reftest_ip
( CHECK (clef_etr2 IS NOT NULL AND clef_etr2>0::bigint))
INHERITS (reference_test);
CREATE TABLE reftest_cit
( CHECK (clef_etr3 IS NOT NULL AND clef_etr3>0::bigint))
INHERITS (reference_test);
CREATE TABLE reftest_div
( CHECK (clef_etr4 IS NOT NULL AND clef_etr4>0::bigint))
INHERITS (reference_test);
CREATE FUNCTION reference_test_handler()
RETURNS TRIGGER AS $$
DECLARE
BEGIN
IF tg_op = 'INSERT' THEN
IF new.clef_etr1 IS NOT NULL AND new.clef_etr1>0 THEN
INSERT INTO reftest_cl
(clef_etr1,clef_etr2,clef_etr3,clef_etr4,ref_datetest,ref_pos1,ref_pos2,anadef_clef,typana_clef)
VALUES (new.clef_etr1,new.clef_etr2,new.clef_etr3,new.clef_etr4,new.ref_datetest,new.ref_pos1,
new.ref_pos2,new.anadef_clef,new.typana_clef);
ELSIF new.clef_etr2 IS NOT NULL AND new.clef_etr2>0 THEN
INSERT INTO reftest_ip
(clef_etr1,clef_etr2,clef_etr3,clef_etr4,ref_datetest,ref_pos1,ref_pos2,anadef_clef,typana_clef)
VALUES (new.clef_etr1,new.clef_etr2,new.clef_etr3,new.clef_etr4,new.ref_datetest,new.ref_pos1,
new.ref_pos2,new.anadef_clef,new.typana_clef);
ELSIF new.clef_etr3 IS NOT NULL AND new.clef_etr3>0 THEN
INSERT INTO reftest_cit
(clef_etr1,clef_etr2,clef_etr3,clef_etr4,ref_datetest,ref_pos1,ref_pos2,anadef_clef,typana_clef)
VALUES (new.clef_etr1,new.clef_etr2,new.clef_etr3,new.clef_etr4,new.ref_datetest,new.ref_pos1,
new.ref_pos2,new.anadef_clef,new.typana_clef);
ELSIF new.clef_etr4 IS NOT NULL AND new.clef_etr4>0 THEN
INSERT INTO reftest_div
(clef_etr1,clef_etr2,clef_etr3,clef_etr4,ref_datetest,ref_pos1,ref_pos2,anadef_clef,typana_clef)
VALUES (new.clef_etr1,new.clef_etr2,new.clef_etr3,new.clef_etr4,new.ref_datetest,new.ref_pos1,
new.ref_pos2,new.anadef_clef,new.typana_clef);
END IF;
END IF;
IF tg_op = 'UPDATE' THEN
IF old.clef_etr1 IS NOT NULL AND old.clef_etr1>0 THEN
UPDATE reftest_cl SET clef_etr1=new.clef_etr1,clef_etr2=new.clef_etr2_clef,clef_etr3=new.clef_etr3,
clef_etr4=new.clef_etr4,ref_datetest=new.ref_datetest,ref_pos1=new.ref_pos1,
ref_pos2=new.ref_pos2,anadef_clef=new.anadef_clef,typana_clef=new.typana_clef;
ELSEIF old.clef_etr2 IS NOT NULL AND old.clef_etr2>0 THEN
UPDATE reftest_ip SET clef_etr1=new.clef_etr1,clef_etr2=new.clef_etr2_clef,clef_etr3=new.clef_etr3,
clef_etr4=new.clef_etr4,ref_datetest=new.ref_datetest,ref_pos1=new.ref_pos1,
ref_pos2=new.ref_pos2,anadef_clef=new.anadef_clef,typana_clef=new.typana_clef;
ELSEIF old.clef_etr3 IS NOT NULL AND old.clef_etr3>0 THEN
UPDATE reftest_cit SET clef_etr1=new.clef_etr1,clef_etr2=new.clef_etr2_clef,clef_etr3=new.clef_etr3,
clef_etr4=new.clef_etr4,ref_datetest=new.ref_datetest,ref_pos1=new.ref_pos1,
ref_pos2=new.ref_pos2,anadef_clef=new.anadef_clef,typana_clef=new.typana_clef;
ELSEIF old.clef_etr4 IS NOT NULL AND old.clef_etr4>0 THEN
UPDATE reftest_div SET clef_etr1=new.clef_etr1,clef_etr2=new.clef_etr2_clef,clef_etr3=new.clef_etr3,
clef_etr4=new.clef_etr4,ref_datetest=new.ref_datetest,ref_pos1=new.ref_pos1,
ref_pos2=new.ref_pos2,anadef_clef=new.anadef_clef,typana_clef=new.typana_clef;
END IF;
END IF;
IF tg_op = 'DELETE' THEN
IF old.clef_etr1 IS NOT NULL AND old.clef_etr1>0 THEN
DELETE FROM reftest_cl;
ELSEIF old.clef_etr2 IS NOT NULL AND old.clef_etr2>0 THEN
DELETE FROM reftest_ip;
ELSEIF old.clef_etr3 IS NOT NULL AND old.clef_etr3>0 THEN
DELETE FROM reftest_cit;
ELSEIF old.clef_etr4 IS NOT NULL AND old.clef_etr4>0 THEN
DELETE FROM reftest_div;
END IF;
END IF;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER reference_test_handler_trg
BEFORE INSERT OR UPDATE OR DELETE
ON reference_test
FOR EACH ROW
EXECUTE PROCEDURE reference_test_handler();