Оракул внешних ключевых проблем с несколькими табличными вставками и каплями

StackOverflow https://stackoverflow.com/questions/4156873

Вопрос

У нас есть единственная таблица, которую мы хотим расстаться на дереве столов на основе конкретного столбца источника. Я хотел попробовать использовать многопользовательскую вставку, но, похоже, что если я вставлю BLOB в подпалую таблицу, я заводил нарушение ограничения ключей внешнего ключа.

Я не думаю, что это нарушает Правила о многобольных вставках Но я мог быть не прав ...

Я надеюсь, что кто-то мог указать мне еще несколько углубленных ресурсов вокруг того, что на самом деле происходит здесь, чтобы я мог чувствовать себя уверенно, что какое-либо решение будет работать в рамках смешивания Liquibase на базах данных Oracle 9i -> 11G.

Надеюсь, упрощенный сценарий

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)
 );

Источник содержит наши исходные данные. DEST будет нашим родительским столом, с детьми dest_one и dest_two (которые будут содержать информацию о вещах типа «один» или «два» соответственно). Вещи типа у одного есть контент, но вещи типа два нет.

Неудачная попытка

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');

Как уже упоминалось ранее, я завел нарушение ограниченного ключа внешнего ключа здесь. Чтобы дополнительно иллюстрировать, что BLOB был проблемой, который я попробовал два отдельных подобных запроса (ниже), реализующую то, что не работает, не выполнил вставку BLOB, но с ошибками вставки BLOB.

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 */

Решение 1 - традиционные вставки

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';

Один вариант, который я рассматриваю, возвращается к нескольким отдельным заявлениям вставки, но в отличие от того, как я уже говорил их здесь, я обеспокоен тем, что мне придется убедиться, что я пишу свои вкладыши под столом, чтобы только попытаться вставить эти ряды В родительском столе DEST ... Мне нужно больше исследований о том, как Liquibase обрабатывает несколько операторов SQL в тех же изменений.

Решение 2 - временно отключить ограничения внешних ключей

ALTER TABLE dest_one DISABLE CONSTRAINT XFK1DEST_ONE;

Вставьте все, когда 1 = 1, затем в значения DEST (PK, TYPE) (PK, TYPE) при типе = «один», затем в значения DEST_ONE (PKFK, DATA) (PK, Content) при типе = «два», затем в DEST_TWO ( PKFK) Значения (PK) Выберите PK, введите, utl_raw.cast_to_raw (контент) как контент из источника, где введите («один», «два»);

ALTER TABLE DEST_ONE Включить ограничение XFK1Dest_One;

Это решение, которое я склоняюсь к. Хотя отключение внешнего ключа на моем столе BLOB, кажется, заставляют его работать в моей тестовой среде (10G - 10.2.0.1.0), я не уверен, что я также должен отключить внешний ключ на таблице Nonblob (Из-за того, как 9i, 11g или другие версии 10G могут вести себя). Любые ресурсы здесь тоже будут оценены.

Огромное спасибо!

Это было полезно?

Решение

Другое решение было бы отложить оценку ограничения до коммита. Я подозреваю (но не уверен), что Multi-Table INSERT представляет собой строки в порядке, кроме того, который вы ожидаете и хотите. Воссоздайте свои ограничения следующим образом:

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;

Это повторно создает ограничения, чтобы они могли быть отложены и отложены с момента создания времени. Затем попробуйте вашу оригинальную вставку снова.

Поделитесь и наслаждайтесь.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top