Bạn có thể sử dụng gói DBMS_SQL
để tạo và truy cập con trỏ bằng các truy vấn động.
Tuy nhiên, việc truy cập một cột theo tên không thực sự đơn giản vì DBMS_SQL
gói sử dụng định vị và trong một truy vấn động, chúng tôi có thể không biết thứ tự của các cột trước khi thực thi.
Hơn nữa, trong ngữ cảnh của câu hỏi này, có vẻ như chúng tôi không biết cột nào chúng tôi muốn hiển thị tại thời điểm biên dịch, chúng tôi sẽ giả định rằng cột chúng tôi muốn hiển thị được cung cấp dưới dạng tham số.
Chúng tôi có thể sử dụng DBMS_SQL.describe_columns
để phân tích các cột của SELECT
truy vấn sau khi nó đã được phân tích cú pháp để tạo ánh xạ động của các cột. Chúng tôi sẽ giả định rằng tất cả các cột có thể được chuyển thành VARCHAR2
vì chúng tôi muốn hiển thị chúng bằng DBMS_OUTPUT
.
Đây là một ví dụ:
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
Chúng ta có thể gọi thủ tục này bằng một truy vấn chỉ được biết tại thời điểm chạy:
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
Hãy thận trọng với SQL động:nó có các đặc quyền giống như người dùng và do đó có thể thực thi bất kỳ DML và DDL nào câu lệnh được phép cho lược đồ này.
Ví dụ:quy trình trên có thể được sử dụng để tạo hoặc thả một bảng:
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