sql >> Base de Datos >  >> RDS >> Oracle

Incluir el valor de RowId en la tabla anidada

ROWID es una pseudocolumna , no forma parte de la vista del diccionario de datos de la tabla (por ejemplo, no aparece en dba_tab_columns ), por lo que no se incluye en el %rowtype . Un registro PL/SQL, que es de lo que está construyendo una tabla PL/SQL, no tiene almacenamiento físico, por lo que no tiene ID de fila real o pseudo.

Si realmente desea almacenar el ID de fila en un registro/tabla, deberá declarar el tipo explícitamente:

create or replace package dat_pkg is

    type typ_dat_rec is record (
        data_id     data_test.data_id%type,
        data_value  data_test.data_value%type,
        data_rowid  rowid);

    type typ_dat_tst is table of data_test%rowtype index by pls_integer;

    procedure proc_test (p_dat  typ_dat_tst);

end dat_pkg;
/

No puede llamar al campo de registro simplemente rowid como ese es un tipo de datos, lo prefijé con data_ pero es posible que prefieras otra cosa. Y luego necesita usar ese nombre de campo en el cuerpo de su paquete, obviamente:

create or replace package body dat_pkg is

    procedure proc_test (p_dat  typ_dat_tst)
    is
    begin

        for i in 1..p_dat.count loop

            update  data_test        
            set     data_value  = p_dat(i).data_value  
            where   data_id     = p_dat(i).data_id
            and     rowid       = p_dat(i).data_rowid;

        end loop;

    end proc_test;

end dat_pkg;
/

Podría, como sugirió, almacenar todo el tipo de fila y el ID de fila como dos campos en el tipo de registro:

create or replace package dat_pkg is

    type typ_dat_rec is record (
        data_rec    data_test%rowtype,
        data_rowid  rowid);

    type typ_dat_tst is table of typ_dat_rec index by pls_integer;

    procedure proc_test (p_dat  typ_dat_tst);

end dat_pkg;
/

pero eso hace que referirse a los campos sea un poco más incómodo:

...
        for i in 1..p_dat.count loop

            update  data_test        
            set     data_value  = p_dat(i).data_rec.data_value  
            where   data_id     = p_dat(i).data_rec.data_id
            and     rowid       = p_dat(i).data_rowid;

        end loop;
...

y probablemente también hará que poblar la colección sea más incómodo. Como tiene que conocer todos los nombres de columnas/campos de todos modos para poder referirse a ellos en el ciclo, no estoy seguro de que haya mucha ventaja, pero puede que lo encuentre más ordenado.

Por supuesto, hacer esto supone que su colección se completa a partir de un subconjunto de datos de la tabla en la misma base de datos e incluso en la misma sesión, ya que el rowid de una fila puede cambiar con el tiempo. También es posible que desee buscar en el forall sintaxis para reemplazar su for bucle, dependiendo de lo que realmente esté haciendo. (Pero también debe considerar si necesita la colección en absoluto; si solo está completando la colección y luego usándola para la actualización, entonces una sola actualización de SQL sería aún más rápida...)