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

Akses kursor dengan nama kolom secara dinamis

Anda dapat menggunakan paket DBMS_SQL untuk membuat dan mengakses kursor dengan kueri dinamis.

Namun tidak mudah untuk mengakses kolom dengan nama karena DBMS_SQL package menggunakan positioning dan dalam query dinamis kita mungkin tidak mengetahui urutan kolom sebelum dieksekusi.

Selanjutnya, dalam konteks pertanyaan ini, tampaknya kita mungkin tidak mengetahui kolom mana yang ingin kita tampilkan pada waktu kompilasi, kita akan menganggap bahwa kolom yang ingin kita tampilkan diberikan sebagai parameter.

Kita dapat menggunakan DBMS_SQL.describe_columns untuk menganalisis kolom dari SELECT kueri setelah diurai untuk membangun pemetaan kolom yang dinamis. Kami akan berasumsi bahwa semua kolom dapat dimasukkan ke VARCHAR2 karena kita ingin menampilkannya dengan DBMS_OUTPUT .

Ini contohnya:

SQL> CREATE OR REPLACE PROCEDURE display_query_column(p_query VARCHAR2,
  2                                                   p_column VARCHAR2) IS
  3     l_cursor            INTEGER;
  4     l_dummy             NUMBER;
  5     l_description_table dbms_sql.desc_tab3;
  6     TYPE column_map_type IS TABLE OF NUMBER INDEX BY VARCHAR2(32767);
  7     l_mapping_table column_map_type;
  8     l_column_value  VARCHAR2(4000);
  9  BEGIN
 10     l_cursor := dbms_sql.open_cursor;
 11     dbms_sql.parse(l_cursor, p_query, dbms_sql.native);
 12     -- we build the column mapping
 13     dbms_sql.describe_columns3(l_cursor, l_dummy, l_description_table);
 14     FOR i IN 1 .. l_description_table.count LOOP
 15        l_mapping_table(l_description_table(i).col_name) := i;
 16        dbms_sql.define_column(l_cursor, i, l_column_value, 4000);
 17     END LOOP;
 18     -- main execution loop
 19     l_dummy := dbms_sql.execute(l_cursor);
 20     LOOP
 21        EXIT WHEN dbms_sql.fetch_rows(l_cursor) <= 0;
 22        dbms_sql.column_value(l_cursor, l_mapping_table(p_column), l_column_value);
 23        dbms_output.put_line(l_column_value);
 24     END LOOP;
 25     dbms_sql.close_cursor(l_cursor);
 26  END;
 27  /

Procedure created

Kita dapat memanggil prosedur ini dengan kueri yang hanya diketahui saat run-time:

SQL> set serveroutput on
SQL> exec display_query_column('SELECT * FROM scott.emp WHERE rownum < 5', 'ENAME');
SMITH
ALLEN
WARD
JONES

PL/SQL procedure successfully completed

SQL> exec display_query_column('SELECT * FROM scott.emp WHERE rownum < 5', 'EMPNO');
7369
7499
7521
7566

PL/SQL procedure successfully completed

Berhati-hatilah dengan SQL dinamis:ia memiliki hak istimewa yang sama dengan pengguna dan oleh karena itu dapat menjalankan DML dan DDL apa pun pernyataan diperbolehkan untuk skema ini.

Misalnya, prosedur di atas dapat digunakan untuk membuat atau menghapus tabel:

SQL> exec display_query_column('CREATE TABLE foo(id number)', '');
begin display_query_column('CREATE TABLE foo(id number)', ''); end;
ORA-01003: aucune instruction analysée
ORA-06512: à "SYS.DBMS_SQL", ligne 1998
ORA-06512: à "APPS.DISPLAY_QUERY_COLUMN", ligne 13
ORA-06512: à ligne 1

SQL> desc foo
Name Type   Nullable Default Comments 
---- ------ -------- ------- -------- 
ID   NUMBER Y      


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Oracle (ORA-02270):tidak ada kunci unik atau kunci utama yang cocok untuk kesalahan daftar kolom ini

  2. Mengonversi OracleParameter.Value ke Int32

  3. Menggunakan pernyataan Gabung untuk tabel tunggal

  4. org.hibernate.MappingException:Tidak ada pemetaan Dialek untuk tipe JDBC:2002

  5. Java Date.toString di Oracle TO_DATE