カーソルの列に動的にアクセスできますか? つまり、名前で?このようなもの:
declare
v_cursor := select * from emp;
begin
FOR reg IN v_cursor LOOP
dbms_output.put_line(**reg['column_name_as_string']**);
end loop;
end;
太字部分が PL/SQL ではないことはわかっていますが、そのようなものを探していますが、どこにも見つかりません。
カーソルの列に動的にアクセスできますか? つまり、名前で?このようなもの:
declare
v_cursor := select * from emp;
begin
FOR reg IN v_cursor LOOP
dbms_output.put_line(**reg['column_name_as_string']**);
end loop;
end;
太字部分が PL/SQL ではないことはわかっていますが、そのようなものを探していますが、どこにも見つかりません。
このパッケージDBMS_SQL
を使用して、動的クエリでカーソルを作成およびアクセスできます。
DBMS_SQL
ただし、パッケージは配置を使用し、動的クエリでは実行前に列の順序がわからない可能性があるため、列に名前でアクセスするのは簡単ではありません。
さらに、この質問のコンテキストでは、コンパイル時に表示する列がわからない可能性があるようです。表示する列はパラメーターとして指定されると想定します。
列の動的マッピングを構築するために解析された後DBMS_SQL.describe_columns
、クエリの列を分析するために使用できます。で表示したいのでSELECT
、すべての列を にキャストできると仮定します。VARCHAR2
DBMS_OUTPUT
次に例を示します。
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
このプロシージャは、実行時にのみ認識されるクエリで呼び出すことができます。
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
動的 SQL には注意してください。動的 SQL はユーザーと同じ権限を持っているため、このスキーマで許可されている DMLおよび DDLステートメントを実行できます。
たとえば、上記の手順を使用してテーブルを作成または削除できます。
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
次のような意味です。
declare
cursor sel_cur is
select * from someTable;
begin
for rec in sel_cur
loop
dbms_output.put_line('col1: ' || rec.col1);
end loop;
end;
可能であれば、クエリを動的にするのがおそらく最も簡単です。
DECLARE
v_cursor SYS_REFCURSOR;
dynamic_column_name VARCHAR2(30) := 'DUMMY';
column_value VARCHAR2(32767);
BEGIN
OPEN v_cursor FOR 'SELECT ' || dynamic_column_name || ' FROM dual';
LOOP
FETCH v_cursor INTO column_value;
EXIT WHEN v_cursor%NOTFOUND;
dbms_output.put_line( column_value );
END LOOP;
CLOSE v_cursor;
END;
ハードコードされた列を名前で動的に選択したい場合はSELECT *
、Vincent が示唆するように DBMS_SQL を使用してそれを行うことができると思いますが、それはやや複雑になります。