Oracle Insert через Select из нескольких таблиц, где в одной таблице может не быть строки

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

  •  02-07-2019
  •  | 
  •  

Вопрос

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

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

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 и recipient, если найдено совпадение для их соответствующих кодов.К сожалению, recipient_code имеет значение null, и поэтому ?значение подстановки может быть равно null.Конечно, неявное соединение не возвращает строку, поэтому строка не вставляется в мою таблицу.

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

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

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

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

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

Решение

Внешние соединения в этом случае не работают "как ожидалось", потому что вы явно сообщили 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 к каждому предложению where ИЛИ использовать агрегат, такой как MAX или MIN .Это, конечно, может быть не лучшим решением для всех случаев.

[Редактировать] Согласно комментарию,

  (SELECT account_type_standard_seq.nextval FROM DUAL),

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

  account_type_standard_seq.nextval,

Другие советы

Слегка упрощенная версия решения Oglester (последовательность не требует выбора из 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 = ?)
)

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

Вы можете справиться с возможностью того, что ваша переменная bind будет равна null, используя OR следующим образом.Вы бы привязали то же самое к первым двум переменным bind.

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

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

Попробуй:

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 = ?
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 = ?
insert into received_messages(id, content, status)
    values (RECEIVED_MESSAGES_SEQ.NEXT_VAL, empty_blob(), '');
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top