Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Uwzględnij wartość RowId w tabeli zagnieżdżonej

ROWID to pseudokolumna , nie jest częścią widoku słownika danych tabeli (np. nie pojawia się w dba_tab_columns ), więc nie jest zawarte w %rowtype . Rekord PL/SQL – z którego konstruujesz tablicę PL/SQL – nie ma fizycznej pamięci, więc nie ma rzeczywistego ani pseudo-rowidu.

Jeśli naprawdę chcesz przechowywać identyfikator wiersza w rekordzie/tabeli, musisz jawnie zadeklarować typ:

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;
/

Nie możesz wywołać pola rekordu tylko rowid ponieważ jest to typ danych, więc poprzedziłem go przedrostkiem data_ ale może wolisz coś innego. A potem musisz użyć tej nazwy pola w treści swojego pakietu, oczywiście:

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;
/

Możesz, zgodnie z sugestią, przechowywać cały typ wiersza i identyfikator wiersza jako dwa pola w typie rekordu:

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;
/

ale to sprawia, że ​​odwoływanie się do pól jest nieco bardziej niezręczne:

...
        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;
...

i prawdopodobnie sprawi to, że zapełnianie kolekcji będzie również trudniejsze. Ponieważ i tak musisz znać wszystkie nazwy kolumn/pól, aby móc odwoływać się do nich w pętli, nie jestem pewien, czy jest to duża zaleta, ale może się to okazać ładniejsze.

Oczywiście wykonanie tego w ogóle zakłada, że ​​twoja kolekcja jest wypełniana z podzbioru danych z tabeli w tej samej bazie danych, a nawet sesji, ponieważ rowid wiersza może się zmieniać w czasie. Możesz także zajrzeć do forall składnia zastępująca for pętla, w zależności od tego, co naprawdę robisz. (Ale powinieneś również zastanowić się, czy w ogóle potrzebujesz kolekcji - jeśli po prostu zapełnisz kolekcję, a następnie użyjesz jej do aktualizacji, pojedyncza aktualizacja SQL będzie jeszcze szybsza...)




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak napisać klauzulę Order By przed klauzulą ​​Where

  2. ORA-06553:PLS-801:błąd wewnętrzny [55018] podczas testowania funkcji zwracającej ROWTYPE

  3. Błąd składni Brak słowa kluczowego w instrukcji case w klauzuli WHERE

  4. Jak rozwiązać ORA-04063:widok SYS.ALL_QUEUE_TABLES zawiera błędy?

  5. Zapytanie Oracle PL/SQL nie kompiluje się