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

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

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

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

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

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

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

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

ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
12
0
153 605
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Ответ принят как подходящий

В этом случае внешние соединения не работают «должным образом», потому что вы явно указали 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. Конечно, это может быть не лучшим решением для всех случаев.

[Edit] За комментарий,

  (SELECT account_type_standard_seq.nextval FROM DUAL),

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

  account_type_standard_seq.nextval,

Разве это не проблема, если в tax_status или в поле recipient есть несколько записей и что происходит с NULL recipient_code?

Cade Roux 25.09.2008 08:55

Просто попробовал, и нулевой код получателя приводит к нулю для столбца recipient_id в account_type_standard. Не знаю о нескольких записях, но в моем случае таблицы имеют уникальные коды, так что я в порядке.

Mikezx6r 25.09.2008 16:39

По словам Тони Эндрюса, для значения последовательности не требуется Select from DUAL. Можно просто account_type_standard_seq.nextval.

Mikezx6r 26.09.2008 16:22

В вопросе мне было непонятно, является ли ts.tax_status_code первичным или альтернативным ключом или нет. То же самое и с recipient_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))

Разве этот запрос не может быть очень медленным?

Greg Ogle 25.09.2008 21:51

Да, отсюда и мое утверждение о «Если вас беспокоит производительность ...»

WW. 13.11.2008 00:37

Пытаться:

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 = ?

Вы знаете, эффективнее ли это ответа Оглестера? Если так, то меня можно убедить принять этот ответ. В противном случае, я думаю, что наличие всех выбранных элементов в их соответствующем местоположении более ясно, чем наличие длинных предложений from и where. Я знаю, что у меня было, но ...

Mikezx6r 25.09.2008 16:42

Я не думаю, что это значительно лучше (или хуже). Однако решение Oglester не требует выбора из DUAL - я опубликовал новый ответ, который показывает измененную версию (просто немного более эффективен)

Tony Andrews 26.09.2008 14:46

Немного упрощенная версия решения 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 = ?)
)

insert into received_messages(id, content, status)
    values (RECEIVED_MESSAGES_SEQ.NEXT_VAL, empty_blob(), '');

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 = ?

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