sql >> Database >  >> RDS >> Oracle

Cursor dynamisch op kolomnaam openen

U kunt het pakket DBMS_SQL gebruiken om cursors te maken en te openen met dynamische zoekopdrachten.

Het is echter niet echt eenvoudig om toegang te krijgen tot een kolom op naam, omdat de DBMS_SQL pakket maakt gebruik van positionering en in een dynamische zoekopdracht weten we mogelijk niet de volgorde van de kolommen voor de uitvoering.

Bovendien lijkt het er in de context van deze vraag op dat we misschien niet weten welke kolom we willen weergeven tijdens het compileren, we gaan ervan uit dat de kolom die we willen weergeven als parameter wordt gegeven.

We kunnen DBMS_SQL.describe_columns gebruiken om de kolommen van een SELECT te analyseren query nadat deze is geparseerd om een ​​dynamische toewijzing van de kolommen te maken. We gaan ervan uit dat alle kolommen kunnen worden gegoten in VARCHAR2 omdat we ze willen weergeven met DBMS_OUTPUT .

Hier is een voorbeeld:

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

We kunnen deze procedure aanroepen met een query die alleen bekend is tijdens runtime:

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

Wees voorzichtig met dynamische SQL:deze heeft dezelfde rechten als de gebruiker en kan daarom elke DML en DDL uitvoeren statement toegestaan ​​voor dit schema.

De bovenstaande procedure kan bijvoorbeeld worden gebruikt om een ​​tabel aan te maken of te verwijderen:

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. MySQL VERVANGEN in een automatisch oplopende rij

  2. MySQL Group By met het hoogste N-nummer van elke soort

  3. Gegevensvisualisatie met Apache Zeppelin - Zelfstudie

  4. Eenvoudige If Else-instructie in sql