2010-07-15 25 views
6

Tengo una tabla de Oracle con tablas anidadas en algunas de las columnas. Ahora, necesito poder actualizar todos los registros en cada tabla anidada, en cada uno de los registros de la tabla principal. ¿Cómo se logra esto? Cualquiera de las formas en que lo he intentado, obtengo errores sobre la imposibilidad de realizar actualizaciones en esa vista o la sub consulta de una sola fila muestra más de una fila.actualizar registros múltiples en tablas anidadas múltiples en Oracle

he aquí un ejemplo de para ilustrar. Puedo ejecutar una actualización de esta manera:

UPDATE TABLE(select entity.name 
       from entity 
       where entity.uidn = 2) 
    SET last = 'Decepticon', 
    change_date = SYSDATE, 
    change_user = USER 
    WHERE first = 'Galvatron'; 

pero en este caso, la cláusula de mesa se está ejecutando en una sola tabla anidada a partir de una sola fila. ¿Cómo se llevaría a cabo una actualización como esta si no quisieras solo la entidad.uidn que equivale a 2?

gracias!

Respuesta

10

Quizás la mejor razón para evitar tablas anidadas en una base de datos es que son difíciles de trabajar, y la sintaxis es poco documentada y difícil de asimilar.

¡En marcha!

Aquí hay una tabla con una tabla anidada.

SQL> select f.force_name, t.id, t.name 
    2 from transformer_forces f, table(f.force_members) t 
    3/

FORCE_NAME   ID NAME 
---------- ---------- -------------------- 
Autobot    0 Metroplex 
Autobot    0 Optimus Prime 
Autobot    0 Rodimus 
Decepticon   0 Galvatron 
Decepticon   0 Megatron 
Decepticon   0 Starscream 
Dinobot    0 Grimlock 
Dinobot    0 Swoop 
Dinobot    0 Snarl 

9 rows selected. 

SQL> 

Como se puede ver, cada elemento de la tabla anidada el atributo ID se establece en cero en todos los casos. Lo que nos gustaría hacer es actualizarlos a todos. ¡Pero Ay!

SQL> update table 
    2 (select force_members from transformer_forces) t 
    3 set t.id = rownum 
    4/
(select force_members from transformer_forces) t 
    * 
ERROR at line 2: 
ORA-01427: single-row subquery returns more than one row 


SQL> 

Es posible actualizar todos los elementos de una tabla anidada para una sola fila en la mesa de recogida:

SQL> update table 
    2  (select force_members from transformer_forces 
    3   where force_name = 'Autobot') t 
    4  set t.id = rownum 
    5/

3 rows updated. 

SQL> 

Pero la única manera de hacer que para toda la tabla es una Bucle PL/SQL. ¡Yuck!

Existe una alternativa: use a Nested Table Locator, mediante la sugerencia NESTED_TABLE_GET_REFS. Esto es una cosa particularmente oscuro (que no está en la main list of hints), pero no el truco:

SQL> update /*+ NESTED_TABLE_GET_REFS */ force_members_nt 
    2 set id = rownum 
    3/

9 rows updated. 

SQL> select f.force_name, t.id, t.name 
    2 from transformer_forces f, table(f.force_members) t 
    3/

FORCE_NAME   ID NAME 
---------- ---------- -------------------- 
Autobot    1 Metroplex 
Autobot    2 Optimus Prime 
Autobot    3 Rodimus 
Decepticon   4 Galvatron 
Decepticon   5 Megatron 
Decepticon   6 Starscream 
Dinobot    7 Grimlock 
Dinobot    8 Swoop 
Dinobot    9 Snarl 

9 rows selected. 

SQL> 

Este indicio nos permite pasar por alto la mesa de recogida por completo y trabajamos con la tabla anidada real. Es decir, el objeto especificado en la cláusula de almacenamiento Tabla anidada:

create table transformer_forces (
    force_name varchar2(10) 
    , force_members transformers_nt) 
nested table force_members store as force_members_nt return as value; 
            ^^^^^^^^^^^^^^^^ 
+0

¡Guau, gracias! Qué gran resumen completo, espero que esto ayude a otros con el mismo problema. He encontrado que trabajar con las tablas anidadas es más intuitivo en algunos casos (especialmente cuando se trata de una aplicación java orientada a objetos), pero un poco engorroso en otros- – chrismarx

Cuestiones relacionadas