从pl sql中的rowtype变量中选择动态列值

时间:2017-02-23 13:15:34

标签: oracle plsql

我需要从rowtype变量中获取特定的列值。我的示例代码是

declare
  col_name varchar2(100);
  col_val varchar2(100);
  TYPE column_table_type IS TABLE OF COLUMN_TABLE%ROWTYPE;
  column_table column_table_type ;

begin
 SELECT * BULK COLLECT INTO column_table FROM COLUMN_TABLE;
 for data_table in (select * from DATA_TABLE)
 loop
   for i in column_table.first .. column_table.count
   loop
     col_name=column_table(i).COLUMN_NAME; 
     /*
        How to get the col_val for col_name from the data_table with out extra query.
     */
   end loop;
 end loop
end;
/

COLUMN_TABLE:

COLUMN_NAME
----------------  
emp_name 
emp_id
emp_addr

DATA_TABLE:

emp_name   emp_id   emp_addr
----------------------------
  A          1        aaaa
  B          2        bbbb
  C          3        cccc 

需要以最佳方式编写这段代码。每当我得到col_name时获取值'A'是第一行集的emp_name。

这里DATA_TABLE包含很多列,但我只需要从列表中获取的特定列,并且需要列名和值以供进一步处理。

请帮助我。

2 个答案:

答案 0 :(得分:3)

您无法通过其他变量动态引用列/字段名称。

您需要动态处理整个data_table查询;这是一个the dbms_sql package的演示:

declare
  l_col_name varchar2(100);
  l_col_val varchar2(100);
  type t_col_tab is table of column_table%rowtype;
  l_col_tab t_col_tab;

  -- for dbms_sql
  l_c pls_integer;
  l_col_cnt pls_integer;
  l_desc_t dbms_sql.desc_tab;
  l_rc pls_integer;
  l_varchar varchar2(4000);
begin
  select * bulk collect into l_col_tab from column_table;

  -- create cursor and prepare from original query
  l_c := dbms_sql.open_cursor;
  dbms_sql.parse(c=>l_c, statement=>'select * from data_table',
    language_flag=>dbms_sql.native);
  dbms_sql.describe_columns(c => l_c, col_cnt => l_col_cnt,
    desc_t => l_desc_t);

  for i in 1..l_col_cnt loop
    dbms_sql.define_column(c=>l_c, position=>i,
      column=>l_varchar, column_size=>4000);
  end loop;

  l_rc := dbms_sql.execute(c=>l_c);

  while dbms_sql.fetch_rows(c=>l_c) > 0 loop
    for i in 1..l_col_cnt loop
      for j in 1..l_col_tab.count loop
        if l_desc_t(i).col_name = l_col_tab(j).column_name then
          -- same column
          dbms_sql.column_value(l_c, i, l_varchar);
          dbms_output.put_line('Row ' || dbms_sql.last_row_count
           || ': ' || l_desc_t(i).col_name
           || ' = ' || l_varchar);
        end if;
      end loop;
    end loop;
  end loop;

  dbms_sql.close_cursor(l_c);
end;
/

解析并执行游标查询,表描述允许比较列名。这只是打印出信息,但显然你可以随心所欲地做任何事情。

将虚拟表创建为:

create table data_table(id number, column_1 date, column_2 varchar2(10), column_3 varchar2(10));
insert into data_table (id, column_1, column_2, column_3) values (1, date '2017-01-01', 'dummy', 'first');
insert into data_table (id, column_1, column_2, column_3) values (2, date '2017-02-01', 'dummy', 'second');

create table column_table (column_name varchar2(30));
insert into column_table (column_name) values ('ID');
insert into column_table (column_name) values ('COLUMN_3');

...这会得到输出:

Row 1: ID = 1
Row 1: COLUMN_3 = first
Row 2: ID = 2
Row 2: COLUMN_3 = second

PL/SQL procedure successfully completed.

答案 1 :(得分:0)

表:

create table column_table(column_name varchar2(100), column_value varchar2(100));

您可以在不使用批量收集的情况下执行此操作。简单的FOR循环就足够了。

查询:

declare
    col_name column_table.column_name%type;
    col_val column_table.column_value%type;
begin
    for data_table in (SELECT * FROM COLUMN_TABLE)
    loop
        col_name  := data_table.COLUMN_NAME; 
        col_val := data_table.COLUMN_VALUE;
        dbms_output.put_line(col_name ||' '|| col_val);
    end loop;
end;
/

查询2:

使用bulk collect

declare
    col_name column_table.column_name%type;
    col_val column_table.column_value%type;
    type ct_tab is table of column_table%rowtype;
    v_ct ct_tab;
begin
    select * bulk collect into v_ct
    from column_table;

    for i in 1..v_ct.count loop
        col_name := v_ct(i).column_name;
        col_val := v_ct(i).column_value;
        dbms_output.put_line(col_name ||' '|| col_val);
    end loop;
end;
/