У меня есть несколько таблиц значений кода, которые содержат код и описание с длинным идентификатором.
Теперь я хочу создать запись для типа учетной записи, которая ссылается на несколько кодов, поэтому у меня есть что-то вроде этого:
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.


В этом случае внешние соединения не работают «должным образом», потому что вы явно указали 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,
Просто попробовал, и нулевой код получателя приводит к нулю для столбца recipient_id в account_type_standard. Не знаю о нескольких записях, но в моем случае таблицы имеют уникальные коды, так что я в порядке.
По словам Тони Эндрюса, для значения последовательности не требуется Select from DUAL. Можно просто account_type_standard_seq.nextval.
В вопросе мне было непонятно, является ли 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))
Разве этот запрос не может быть очень медленным?
Да, отсюда и мое утверждение о «Если вас беспокоит производительность ...»
Пытаться:
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. Я знаю, что у меня было, но ...
Я не думаю, что это значительно лучше (или хуже). Однако решение Oglester не требует выбора из DUAL - я опубликовал новый ответ, который показывает измененную версию (просто немного более эффективен)
Немного упрощенная версия решения 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 = ?
Разве это не проблема, если в tax_status или в поле recipient есть несколько записей и что происходит с NULL recipient_code?