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;
^^^^^^^^^^^^^^^^
¡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