Oracle
 sql >> Teknologi Basis Data >  >> RDS >> Oracle

bagaimana cara mendeklarasikan %ROWTYPE dari variabel yang merupakan SYS_REFCURSOR yang diketik dengan lemah?

Jawaban singkatnya adalah, Anda tidak bisa. Anda perlu mendefinisikan variabel untuk setiap kolom yang akan dikembalikan.

DECLARE
    P_RS SYS_REFCURSOR;
    L_T_COL1 T.COL1%TYPE;
    L_T_COL1 T.COL2%TYPE;
    ...

Dan kemudian ambil ke dalam daftar kolom:

FETCH P_RS INTO L_T_COL1, L_T_COL2, ... ;

Ini menyakitkan tetapi dapat dikelola selama Anda tahu apa yang Anda harapkan di kursor ref. Menggunakan T.* dalam prosedur Anda membuat ini rapuh, karena menambahkan kolom ke tabel akan merusak kode yang menganggapnya tahu kolom apa yang ada dan urutannya. (Anda juga dapat memecahnya di antara lingkungan jika tabel tidak dibuat secara konsisten - Saya telah melihat tempat-tempat di mana pemesanan kolom berbeda di lingkungan yang berbeda). Anda mungkin ingin memastikan bahwa Anda hanya memilih kolom yang benar-benar Anda pedulikan, untuk menghindari keharusan mendefinisikan variabel untuk hal-hal yang tidak akan pernah Anda baca.

Dari 11g Anda dapat menggunakan DBMS_SQL paket untuk mengonversi sys_refcursor . Anda menjadi DBMS_SQL kursor, dan Anda dapat menginterogasinya untuk menentukan kolom. Sebagai contoh dari apa yang dapat Anda lakukan, ini akan mencetak nilai setiap kolom di setiap baris, dengan nama kolom:

DECLARE
    P_RS SYS_REFCURSOR;
    L_COLS NUMBER;
    L_DESC DBMS_SQL.DESC_TAB;
    L_CURS INTEGER;
    L_VARCHAR VARCHAR2(4000);
BEGIN
    CAPITALEXTRACT(P_RS => P_RS);
    L_CURS := DBMS_SQL.TO_CURSOR_NUMBER(P_RS);
    DBMS_SQL.DESCRIBE_COLUMNS(C => L_CURS, COL_CNT => L_COLS,
        DESC_T => L_DESC);

    FOR i IN 1..L_COLS LOOP
        DBMS_SQL.DEFINE_COLUMN(L_CURS, i, L_VARCHAR, 4000);
    END LOOP;

    WHILE DBMS_SQL.FETCH_ROWS(L_CURS) > 0 LOOP
        FOR i IN 1..L_COLS LOOP
            DBMS_SQL.COLUMN_VALUE(L_CURS, i, L_VARCHAR);
            DBMS_OUTPUT.PUT_LINE('Row ' || DBMS_SQL.LAST_ROW_COUNT
                || ': ' || l_desc(i).col_name
                || ' = ' || L_VARCHAR);
        END LOOP;
    END LOOP;

    DBMS_SQL.CLOSE_CURSOR(L_CURS);
END;
/

Itu tidak banyak berguna secara praktis, dan untuk singkatnya saya memperlakukan setiap nilai sebagai string karena saya hanya ingin mencetaknya. Lihat dokumen dan cari contoh untuk aplikasi yang lebih praktis.

Jika Anda hanya menginginkan beberapa kolom dari kursor ref Anda, saya kira, Anda dapat memutar l_desc dan catat posisi dimana column_name adalah apa pun yang Anda minati, sebagai variabel numerik; Anda kemudian bisa merujuk ke kolom dengan variabel itu nanti di mana Anda biasanya menggunakan nama itu dalam loop kursor. Tergantung apa yang Anda lakukan dengan data tersebut.

Tapi kecuali jika Anda mengharapkan untuk tidak mengetahui urutan kolom yang Anda dapatkan kembali, yang tidak mungkin karena Anda tampaknya mengontrol prosedur - dan dengan asumsi Anda menyingkirkan .* s - Anda mungkin jauh lebih baik mengurangi kolom yang dikembalikan seminimal mungkin dan mendeklarasikan semuanya satu per satu.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Bagaimana memilih perbandingan dua kolom sebagai satu kolom di Oracle

  2. Cara Menghapus Spasi Trailing setelah Nama Bulan di Oracle

  3. SQL Tanda kurung kanan tidak ada pada urutan demi pernyataan

  4. seperti apa indeks B-tree pada lebih dari 1 kolom?

  5. EF 4, cara menambahkan kelas parsial