Oracle Insertar mediante Seleccionar de varias tablas donde una tabla puede no tener una fila

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

  •  02-07-2019
  •  | 
  •  

Pregunta

Tengo varias tablas de valores de código que contienen un código y una descripción con un ID largo.

Ahora quiero crear una entrada para un Tipo de cuenta que haga referencia a varios códigos, así que tengo algo como esto:

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

Esto recupera los valores apropiados de tax_status y las tablas de destinatarios si se encuentra una coincidencia para sus respectivos códigos. Desafortunadamente, recipiente_código es anulable y, por lo tanto, El valor de sustitución podría ser nulo. Por supuesto, la unión implícita no devuelve una fila, por lo que una fila no se inserta en mi tabla.

He intentado usar NVL en el? y en el r.recipient_id.

He intentado forzar una unión externa en r.recipient_code =? agregando (+), pero no es una unión explícita, por lo que Oracle aún no agregó otra fila.

¿Alguien sabe de una manera de hacer esto?

Obviamente, puedo modificar la declaración para que haga la búsqueda del receptor_id externamente y tenga un? en lugar de r.recipient_id, y no seleccione nada de la tabla de destinatarios, pero preferiría hacer todo esto en 1 instrucción SQL.

¿Fue útil?

Solución

Las uniones externas no funcionan "como se esperaba" en ese caso porque le ha dicho explícitamente a Oracle que solo desea datos si ese criterio en esa tabla coincide. En ese escenario, la unión externa se vuelve inútil.

Una solución

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

[Editar] Si espera varias filas de una sub-selección, puede agregar ROWNUM = 1 a cada cláusula where O usar un agregado como MAX o MIN. Por supuesto, esta puede no ser la mejor solución para todos los casos.

[Editar] Por comentario,

  (SELECT account_type_standard_seq.nextval FROM DUAL),

puede ser solo

  account_type_standard_seq.nextval,

Otros consejos

Una versión ligeramente simplificada de la solución de Oglester (la secuencia no requiere una selección 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 = ?)
)

No me quedó claro en la pregunta si ts.tax_status_code es una clave primaria o alternativa o no. Lo mismo con recipiente_código. Sería útil saberlo.

Puede lidiar con la posibilidad de que su variable de vinculación sea nula utilizando un OR de la siguiente manera. Usted vincularía lo mismo a las dos primeras variables de vinculación.

Si le preocupa el rendimiento, sería mejor verificar si los valores que pretende vincular son nulos o no y luego emitir una instrucción SQL diferente para evitar el 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))

Prueba:

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(), '');
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top