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

Uzyskaj dostęp do kursora dynamicznie według nazwy kolumny

Możesz użyć pakietu DBMS_SQL do tworzenia i uzyskiwania dostępu do kursorów za pomocą zapytań dynamicznych.

Jednak nie jest łatwo uzyskać dostęp do kolumny według nazwy, ponieważ DBMS_SQL pakiet używa pozycjonowania, a w dynamicznym zapytaniu możemy nie znać kolejności kolumn przed wykonaniem.

Ponadto w kontekście tego pytania wydaje się, że możemy nie wiedzieć, którą kolumnę chcemy wyświetlić w czasie kompilacji, założymy, że kolumna, którą chcemy wyświetlić, jest podana jako parametr.

Możemy użyć DBMS_SQL.describe_columns analizować kolumny SELECT zapytanie po jego przeanalizowaniu w celu zbudowania dynamicznego mapowania kolumn. Założymy, że wszystkie kolumny można rzutować na VARCHAR2 ponieważ chcemy je wyświetlić za pomocą DBMS_OUTPUT .

Oto przykład:

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

Możemy wywołać tę procedurę za pomocą zapytania znanego tylko w czasie wykonywania:

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

Zachowaj ostrożność w przypadku dynamicznego SQL:ma te same uprawnienia co użytkownik i dlatego może wykonywać dowolne DML i DDL instrukcja dozwolona dla tego schematu.

Na przykład powyższa procedura może być użyta do utworzenia lub usunięcia tabeli:

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. Zapisywanie danych w Clob za pomocą Hibernate w Oracle 10g

  2. Wybierz pierwsze 150 wierszy, potem następne 150 i tak dalej?

  3. Łączenie dwóch tabel SQL

  4. Najlepsza nie zerowa kolumna

  5. Wywołanie funkcji oracle z JPA