Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Incluir o valor RowId na tabela aninhada


ROWID é uma pseudocoluna , não faz parte da visualização do dicionário de dados da tabela (por exemplo, não aparece em dba_tab_columns ), portanto, não está incluído no %rowtype . Um registro PL/SQL - que é o que você está construindo em uma tabela PL/SQL - não tem armazenamento físico, portanto, nenhum rowid real ou pseudo.

Se você realmente deseja armazenar o ID da linha em um registro/tabela, você teria que declarar o tipo explicitamente:
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;
/

Você não pode chamar o campo de registro apenas rowid como esse é um tipo de dados, eu o prefixei com data_ mas você pode preferir outra coisa. E então você precisa usar esse nome de campo no corpo do seu pacote, 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;
/

Você pode, como sugeriu, armazenar todo o tipo de linha e o ID da linha como dois campos no 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;
/

mas isso torna a referência aos campos um pouco mais complicada:
...
        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;
...

e provavelmente tornará o preenchimento da coleção mais complicado também. Como você precisa conhecer todos os nomes de colunas/campos de qualquer maneira para poder se referir a eles no loop, não tenho certeza se há muita vantagem, mas você pode achar mais limpo.

Obviamente, fazer isso pressupõe que sua coleção esteja sendo preenchida a partir de um subconjunto de dados da tabela no mesmo banco de dados e até mesmo na sessão, pois o rowid de uma linha pode mudar ao longo do tempo. Você também pode querer olhar para o forall sintaxe para substituir seu for loop, dependendo do que você está realmente fazendo. (Mas você também deve considerar se precisa da coleção - se você estiver apenas preenchendo a coleção e usando isso para a atualização, uma única atualização do SQL seria ainda mais rápida ...)