0

I have a table name SAMPLETABLE this has the tablenames of the tables I require in column TABLENAMES. Lets say the tablenames are TABLEA, TABLEB and TABLEC.

On query

SELECT TABLENAMES FROM SAMPLETABLE WHERE ROWNUM = 1

I get the output the output of TABLENAMES column with TABLEA value.

My problem is, now I want to use this selected value in a select statement. That is,

SELECT * FROM (SELECT TABLENAMES FROM SAMPLETABLE WHERE ROWNUM = 1) 

My idea is that it'd return the contents of TABLEA because when the nested SELECT returns TABLEA, the outer SELECT should capture and display it.

On the contrary, I get the output only of the inner statement, that is,

SELECT TABLENAMES FROM SAMPLETABLE WHERE ROWNUM = 1

and

SELECT * FROM (SELECT TABLENAMES FROM SAMPLETABLE WHERE ROWNUM = 1) 

return the same output.

I want the first SELECT statement to fetch the returned value of second SELECT and display the table. They above query doesn't do that, so how do I do it? And what is wrong with my idea?

I am on Oracle 10g, any help appreciated.

iMan
  • 456
  • 1
  • 7
  • 18
  • You have forgotten to ask the question – zerkms Sep 11 '13 at 06:09
  • That is because you are not doing anything with the result on the inner query. – Vaibhav Desai Sep 11 '13 at 06:12
  • @Vaibhav Desai how do I do 'something' with inner query though? I tried storing on variable, but SELECT * FROM varname returns invalid tablename, how do I get around this. All I want is, the inner result to be used in outer SELECT – iMan Sep 11 '13 at 06:13
  • As table name is not known at compile time you need to use dynamic SQL(`execute immediate`, native dynamic SQL, for instance) to be able to select from a table, name of which is stored as a string literal - you cannot accomplish it with static SQL. – Nick Krasnov Sep 11 '13 at 06:14
  • As Nicholas already pointed out, you need a dynamic sql. Look into procedures/functions. – Vaibhav Desai Sep 11 '13 at 06:17
  • @NicholasKrasnov could you please enlighten me? A link which might help, I got one on OracleDocs, where do I use the EXECUTE IMMEDIATE? – iMan Sep 11 '13 at 06:18
  • @VaibhavDesai how do I store the tablename into a variable though? DECLARE tabe1 varchar(20) BEGIN tabe1 := (SELECT query) ? EXEC IMM outer SELECT? END; – iMan Sep 11 '13 at 06:19

2 Answers2

1

You can do this with help of dynamic sql. Since the table name is obtained during run time you have to frame the query dynamically and run it.

Declare
Tab_Name Varchar2(30);
Begin

  SELECT TABLENAMES into Tab_Name FROM SAMPLETABLE WHERE ROWNUM = 1;

  Execute Immediate 'Select * into (Collection Variable) from ' || Tab_Name;

End
/

I just gave it as example. You declare a variable to get the data out or something else as you need. But when you try to use execute immediate with input parameter read about sql injection and then write your code.

DB_learner
  • 1,026
  • 9
  • 15
  • Thank you for the lead, I'll look into it, and get back if I am stuck elsewhere. – iMan Sep 11 '13 at 06:26
  • I know this is just an example, but when I run this in ORA10g, I get 'Statement processed', you have mentioned that I have to frame query dynamically, isn't that what EXECUTE IMMEDIATE does? If yes, then why wouldn't it work. On searching about SQL Injection, I only get lost in a deeper ocean. Any help appreciated. – iMan Sep 12 '13 at 03:59
  • The place i mentioned "* into (collection)" is not syntax. I gave it as an idea. You cant do a select inside PL/SQL. You have to assign it to a collection/variable and print it out. Look for execute immediate into collection syntax. You will get idea how to proceed. This link has some examples. http://docs.oracle.com/cd/B13789_01/appdev.101/b10807/13_elems017.htm – DB_learner Sep 12 '13 at 06:19
  • And for sql injection, i mentioned about it if and when you are getting a input parameter and using it in your dynamic sql. – DB_learner Sep 12 '13 at 06:20
1

As table name is not known at compile time you need to use dynamic SQL(execute immediate, native dynamic SQL, for instance) to be able to select from a table, name of which is stored as a string literal - you cannot accomplish it with static SQL

Here is an example:

-- table which contains names of other tables
-- in the table_name column
SQL> create table Table_Names as
  2    select 'employees' as table_name
  3      from dual
  4  ;
Table created


SQL> set serveroutput on;

-- example of an anonymous PL/SQL block
-- where native dynamic SQL (execute immediate statement)
-- is used to execute a dynamically formed select statement  
SQL> declare
  2    type T_record is record(   -- example of record for fetched data
  3      f_name varchar2(123),    
  4      l_name varchar2(123)
  5    );  
  6  
  7    l_table_name varchar2(123);  -- variable that will contain table name
  8    l_select     varchar2(201);   
  9    l_record     T_Record;       -- record we are going to fetch data into
 10  begin
 11    select table_name
 12      into l_table_name          -- querying a name of a table
 13     from table_names            -- and storing it in the l_table_name variable
 14    where rownum = 1;
 15  
 16    l_select := 'select first_name, last_name from ' ||
 17                 dbms_assert.simple_sql_name(l_table_name) ||   
 18                ' where rownum = 1';   -- forming a query              
 19  
 20    execute immediate l_select    -- executing the query
 21       into l_record;
 22    -- simple output of data just for the sake of demonstration
 23    dbms_output.put_line('First_name: ' || l_record.f_name || chr(10) ||
 24                         'Last name:  ' || l_record.l_name);
 25  exception
 26    when no_data_found
 27    then dbms_output.put_line('Nothing is found');
 28  end;
 29  /

First_name: Steven
Last name:  King

PL/SQL procedure successfully completed

As a second option you could use weakly typed cursors - refcursors to execute a dynamically formed select statement:

SQL> variable refcur refcursor;
SQL> declare
  2    l_table_name varchar2(123);
  3    l_select     varchar2(201);
  4  begin
  5    select table_name
  6      into l_table_name
  7     from table_names
  8    where rownum = 1;
  9  
 10    l_select := 'select first_name, last_name from ' ||
 11                 dbms_assert.simple_sql_name(l_table_name) ||
 12                ' where rownum = 1';
 13  
 14    open :refcur
 15     for l_select;
 16  
 17  exception
 18    when no_data_found
 19    then dbms_output.put_line('Nothing is found');
 20  end;
 21  /

PL/SQL procedure successfully completed.

SQL> print refcur;

FIRST_NAME           LAST_NAME                                                  
-------------------- -------------------------                                  
Steven               King                                                       

SQL> spool off;

Find out more about cursors and cursor variables

Nick Krasnov
  • 26,886
  • 6
  • 61
  • 78
  • When I use your above example (refcursor) in Oracle 10g, I get a popup box saying to enter value of :REFCUR, whatever I enter, or even if I leave it blank it shows (Invalid SQL Statement), why is that? And why are is statement `OPEN :REFCUR FOR l_select ` ? Thanks – iMan Sep 12 '13 at 03:53
  • @iMan Popup box? Use SQL*PLUS - command line interface. The last example uses SQL*Plus. – Nick Krasnov Sep 12 '13 at 05:28