0

I need to get the specific column value from rowtype variable. My sample code is

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 

Need to write this piece of code in optimal way. To get the value 'A' for whenever i get col_name is emp_name for the first row set.

Here DATA_TABLE contains so many columns, but i need only specific column which are getting from the column table and need column names and values for further processing.

Please help me out from this.

Kancham
  • 11
  • 1
  • 3

2 Answers2

5

You can't refer to a column/field name dynamically via another variable.

You will need to handle the whole data_table query dynamically; this is a demo with 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;
/

The cursor query is parsed and executed, and the table descriptions allow the column names to be compared. This is just printing out the info, but you can do whatever you need with it, obviously.

With dummy tables created as:

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');

... this gets output:

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

PL/SQL procedure successfully completed.
Alex Poole
  • 183,384
  • 11
  • 179
  • 318
  • Thanks Alex and thanks for quick response, It worked as for my question. :) – Kancham Feb 23 '17 at 17:23
  • @AlexPoole https://stackoverflow.com/questions/50581383/while-insert-got-error-like-pls-00904-txt-col1-is-invalid-identifier/50583020?noredirect=1#comment88176362_50583020 Could you please resolve this issue. – Shahin P May 30 '18 at 07:04
0

Table:

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

You can do this without using bulk collect. Simple FOR loop should suffice.

Query:

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;
/

Query 2:

Using 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;
/
Gurwinder Singh
  • 38,557
  • 6
  • 51
  • 76