Oracle Insert via Select из нескольких таблиц, где в одной таблице может не быть строки - PullRequest
12 голосов
/ 25 сентября 2008

У меня есть несколько таблиц значений кода, которые содержат код и описание с длинным идентификатором.

Теперь я хочу создать запись для типа учетной записи, которая ссылается на несколько кодов, поэтому у меня есть что-то вроде этого:

insert into account_type_standard (account_type_Standard_id,
tax_status_id, recipient_id)
( select account_type_standard_seq.nextval,
ts.tax_status_id, r.recipient_id
from tax_status ts, recipient r
where ts.tax_status_code = ?
and r.recipient_code = ?)

При этом извлекаются соответствующие значения из таблиц tax_status и получателей, если найдено совпадение для их соответствующих кодов. К сожалению, receient_code может иметь значение nullable, и поэтому? значение замещения может быть нулевым. Конечно, неявное соединение не возвращает строку, поэтому строка не вставляется в мою таблицу.

Я пытался использовать NVL на? и на r.recipient_id.

Я пытался принудительно выполнить внешнее соединение для r.recipient_code =? добавив (+), но это не явное соединение, поэтому Oracle все еще не добавил еще одну строку.

Кто-нибудь знает способ сделать это?

Я могу, очевидно, изменить инструкцию так, чтобы я выполнял поиск по внешнему получателю и получал? вместо r.recipient_id и вообще не выбирайте из таблицы получателей, но я бы предпочел сделать все это в 1 операторе SQL.

Ответы [ 6 ]

23 голосов
/ 25 сентября 2008

Внешние объединения не работают «как положено» в этом случае, потому что вы явно указали Oracle, что хотите получать данные, только если эти критерии в этой таблице соответствуют. В этом случае внешнее соединение становится бесполезным.

Обходной путь

INSERT INTO account_type_standard 
  (account_type_Standard_id, tax_status_id, recipient_id) 
VALUES( 
  (SELECT account_type_standard_seq.nextval FROM DUAL),
  (SELECT tax_status_id FROM tax_status WHERE tax_status_code = ?), 
  (SELECT recipient_id FROM recipient WHERE recipient_code = ?)
)

[Изменить] Если вы ожидаете, что несколько строк из суб-выбора, вы можете добавить ROWNUM = 1 к каждому, где предложение ИЛИ использовать агрегат, такой как MAX или MIN. Конечно, это может быть не лучшим решением для всех случаев.

[Редактировать] За комментарий,

  (SELECT account_type_standard_seq.nextval FROM DUAL),

может быть просто

  account_type_standard_seq.nextval,
7 голосов
/ 26 сентября 2008

Немного упрощенная версия решения Оглестера (последовательность не требует выбора из DUAL:

INSERT INTO account_type_standard   
  (account_type_Standard_id, tax_status_id, recipient_id) 
VALUES(   
  account_type_standard_seq.nextval,
  (SELECT tax_status_id FROM tax_status WHERE tax_status_code = ?),
  (SELECT recipient_id FROM recipient WHERE recipient_code = ?)
)
3 голосов
/ 25 сентября 2008

Попробуйте:

insert into account_type_standard (account_type_Standard_id, tax_status_id, recipient_id)
select account_type_standard_seq.nextval,
       ts.tax_status_id, 
       ( select r.recipient_id
         from recipient r
         where r.recipient_code = ?
       )
from tax_status ts
where ts.tax_status_code = ?
3 голосов
/ 25 сентября 2008

Мне было непонятно в вопросе, является ли ts.tax_status_code первичным или альтернативным ключом или нет. То же самое с кодом получателя. Это было бы полезно знать.

Вы можете решить, что ваша переменная связывания может быть нулевой, используя ИЛИ, следующим образом. Вы бы связали то же самое с первыми двумя переменными связывания.

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

insert into account_type_standard 
(account_type_Standard_id, tax_status_id, recipient_id)
(
select 
   account_type_standard_seq.nextval,
   ts.tax_status_id, 
   r.recipient_id
from tax_status ts, recipient r
where (ts.tax_status_code = ? OR (ts.tax_status_code IS NULL and ? IS NULL))
and (r.recipient_code = ? OR (r.recipient_code IS NULL and ? IS NULL))
1 голос
/ 28 ноября 2012
insert into account_type_standard (account_type_Standard_id, tax_status_id, recipient_id)
select account_type_standard_seq.nextval,
   ts.tax_status_id, 
   ( select r.recipient_id
     from recipient r
     where r.recipient_code = ?
   )
from tax_status ts
where ts.tax_status_code = ?
0 голосов
/ 20 мая 2010
insert into received_messages(id, content, status)
    values (RECEIVED_MESSAGES_SEQ.NEXT_VAL, empty_blob(), '');
...