Question

Nous avons une seule table que nous voulons briser dans un arbre de tables basées sur une colonne de source particulière. Je voulais essayer d'utiliser un insert à plusieurs colonnes, mais il semble que si j'insérer un blob dans une table sous, je le vent avec une violation de contrainte de clé étrangère.

Je ne pense pas que cela porte atteinte à la règles concernant les inserts multi-tables mais je peux me tromper ...

J'espère que quelqu'un pourrait me pointer vers des ressources plus approfondies autour de ce qui se passe réellement ici, pour que je puisse avoir confiance que toute solution fonctionnera dans le cadre d'un changeset liquibase sur les bases de données Oracle 9i -> 11g .

Si tout va bien simplifié Scénario

CREATE TABLE source (
    pk NUMBER NOT NULL PRIMARY KEY,
    type VARCHAR2(20) NOT NULL,
    content VARCHAR2(20) NOT NULL
);

INSERT INTO source (pk,type,content) values (1,'two','n/a');
INSERT INTO source (pk,type,content) values (2,'one','Content');

CREATE TABLE dest (
    pk NUMBER NOT NULL PRIMARY KEY,
    type VARCHAR2(20) NOT NULL
);


CREATE TABLE dest_one  (
    pkfk NUMBER NOT NULL PRIMARY KEY,
    data BLOB NOT NULL,
    CONSTRAINT XFK1DEST_ONE FOREIGN KEY (pkfk) REFERENCES dest (pk)
);


CREATE TABLE dest_two  (
    pkfk NUMBER NOT NULL PRIMARY KEY,
    CONSTRAINT XFK1DEST_TWO FOREIGN KEY (pkfk) REFERENCES dest (pk)
 );

Source contient nos données originales. dest sera notre table parent, avec les enfants et dest_one dest_two (qui contiendra des informations sur les choses de type « un » ou « deux », respectivement). Les choses d'un type ont un contenu, mais les choses de type deux ne le font pas.

La tentative a échoué

INSERT ALL
WHEN 1=1 THEN INTO dest (pk,type) VALUES (pk,type)
WHEN type='one' THEN INTO dest_one (pkfk,data) VALUES (pk,content)
WHEN type='two' THEN INTO dest_two (pkfk) VALUES (pk)
SELECT pk,type,utl_raw.cast_to_raw(content) as content from source where type in ('one','two');

Comme mentionné précédemment, je me suis retrouvé avec une violation de contrainte de clé étrangère ici. Pour illustrer davantage que le blob était la question que j'ai essayé deux requêtes séparées similaires (ci-dessous) réalisant l'un sans l'insert blob travaillé, mais avec le blob insert a échoué.

INSERT ALL
WHEN 1=1 THEN INTO dest (pk,type) VALUES (pk,type)
WHEN type='two' THEN INTO dest_two (pkfk) VALUES (pk)
SELECT pk,type,utl_raw.cast_to_raw(content) as content from source where type = 'two';
/* Successful */

INSERT ALL
WHEN 1=1 THEN INTO dest (pk,type) VALUES (pk,type)
WHEN type='one' THEN INTO dest_one (pkfk,data) VALUES (pk,content)
SELECT pk,type,utl_raw.cast_to_raw(content) as content from source where type = 'one';
/* ORA-02291: integrity constraint violated, no parent key */

Solution 1 - inserts traditionnels

INSERT INTO dest (pk,type) SELECT pk,type from source where type in ('one','two');
INSERT INTO dest_two (pkfk) SELECT pk from source where type = 'two';
INSERT INTO dest_one (pkfk,data) SELECT pk,utl_raw.cast_to_raw(content) from source where type = 'one';

Une option que je considère va revenir à plusieurs instructions d'insertion séparées, mais contrairement à ce que je l'ai dit les ici, je crains que je vais devoir vous assurer que j'écris mes inserts sous-tableau seulement tenter d'y insérer ces lignes présentent dans le tableau dest parent ... Je dois faire plus de recherches sur la façon dont gère Liquibase plusieurs instructions sQL dans le même changeset.

Solution 2 - Désactivation temporaire des contraintes clés étrangères

ALTER TABLE dest_one DISABLE CONSTRAINT XFK1DEST_ONE;

INSERT ALL WHEN 1=1 THEN INTO dest (pk,type) VALUES (pk,type) WHEN type='one' THEN INTO dest_one (pkfk,data) VALUES (pk,content) WHEN type='two' THEN INTO dest_two (pkfk) VALUES (pk) SELECT pk,type,utl_raw.cast_to_raw(content) as content from source where type in ('one','two');

ALTER TABLE dest_one ENABLE CONSTRAINT XFK1DEST_ONE;

Ceci est la solution que je me penche vers. Bien que la désactivation de la clé étrangère sur ma table de blob semble le faire fonctionner dans mon environnement de test (10g - 10.2.0.1.0), je ne sais pas si je devrais aussi handicapant la clé étrangère sur la table non-blob ainsi (en raison de la façon dont 9i, 11g ou d'autres versions de 10g peuvent se comporter). Toutes les ressources ici aussi seraient appréciés.

Merci un groupe!

Était-ce utile?

La solution

Une autre solution serait de reporter l'évaluation de la contrainte jusqu'à ce que COMMIT. Je pense (mais je ne suis pas sûr) que l'insert multi-table est d'insérer des lignes dans un ordre autre que celui que vous attendez et que vous voulez. Recréez vos contraintes comme suit:

ALTER TABLE DEST_ONE DROP CONSTRAINT XFK1DEST_ONE;

ALTER TABLE DEST_ONE
  ADD CONSTRAINT XFK1DEST_ONE
    FOREIGN KEY (pkfk) REFERENCES dest (pk) 
    INITIALLY DEFERRED DEFERRABLE;

ALTER TABLE DEST_TWO DROP CONSTRAINT XFK1DEST_TWO;

ALTER TABLE DEST_TWO
  ADD CONSTRAINT XFK1DEST_TWO
    FOREIGN KEY (pkfk) REFERENCES dest (pk)
    INITIALLY DEFERRED DEFERRABLE;

Cette re-crée les contraintes afin qu'ils puissent être reportés et sont reportés à partir du moment où ils sont créés. Ensuite, essayez à nouveau votre INSERT d'origine.

Partager et apprécier.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top