A Oracle Inserir via Select de várias tabelas onde uma tabela não podem ter uma linha
Pergunta
Eu tenho um número de tabelas de valores de código que contêm um código e uma descrição com uma id longa.
Agora eu quero criar uma entrada para um tipo de conta que faz referência a um número de códigos, então eu tenho algo parecido com isto:
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 = ?)
Este recupera os valores apropriados das tabelas tax_status e receptores, se for encontrada uma correspondência para os respectivos códigos. Infelizmente, recipient_code é anulável, e, portanto, a? valor de substituição pode ser nulo. Claro, o implícito junção não retornar uma linha, então uma linha não se inserido em minha mesa.
Eu tentei usar NVL no? e na r.recipient_id.
Eu tentei forçar uma junção externa sobre os = r.recipient_code? adicionando (+), mas não é participar de uma explícita, de modo a Oracle ainda não adicionar outra linha.
Alguém sabe de uma maneira de fazer isso?
Eu, obviamente, pode modificar a instrução para que eu fazer a pesquisa do recipient_id externamente, e ter um? em vez de r.recipient_id, e não selecione da tabela de destinatário em tudo, mas eu prefiro fazer tudo isso em declaração 1 SQL.
Solução
Outter junta não funcionam "como esperado", nesse caso, porque você ter dito explicitamente a Oracle só deseja dados se que os critérios em que os jogos de mesa. Nesse cenário, o outter juntar-se torna-se inútil.
Uma forma de contornar
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 = ?)
)
[Edit] Se você espera que várias linhas a partir de uma sub-selecionar, você pode adicionar ROWNUM = 1 para cada cláusula WHERE ou usar um agregado tais como MAX ou MIN. Isto, obviamente, pode não ser a melhor solução para todos os casos.
[Edit] Per comentário,
(SELECT account_type_standard_seq.nextval FROM DUAL),
pode ser apenas
account_type_standard_seq.nextval,
Outras dicas
Uma versão ligeiramente simplificada da solução da Oglester (a seqüência não requer uma escolha de 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 = ?)
)
Não estava claro para mim na questão se ts.tax_status_code é uma chave primária ou suplente ou não. A mesma coisa com recipient_code. Isso seria útil para conhecer.
Você pode lidar com a possibilidade de sua variável de ligação sendo nula usando um OR como segue. Você ligaria a mesma coisa para as duas primeiras variáveis ??de ligação.
Se você está preocupado com o desempenho, você seria melhor para verificar se os valores que pretende vincular são nulos ou não e, em seguida, emitir instrução SQL diferente para evitar o 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))
Tente:
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(), '');