Home > other >  Oracle SQL: select from different tables from the result of a variable
Oracle SQL: select from different tables from the result of a variable

Time:12-29


Hi,
I need to create a select with a condition for the from clause: if the variable is equal to POS the select must be done with table tb_a and if the variable is equal to PRE the selected will be done with the table tb_b.
I tried both ways below, but neither worked.

SELECT * FROM tb_a WHERE '&prod' = 'POS'
UNION ALL 
SELECT * FROM tb_b WHERE '&prod' = 'PRE';

SELECT * 
  FROM
 (CASE '&prod'
  WHEN 'prod' = 'POS' THEN tb_a
  WHEN 'prod' = 'PRE' THEN tb_b
  END);

Can you help me please?

CodePudding user response:

Of course it works.

SQL> create table tb_a as select * from dept where deptno in (10, 20);  --> for POS

Table created.

SQL> create table tb_b as select * from dept where deptno in (30, 40);  --> for PRE

Table created.

SQL> select * from tb_a where '&&prod' = 'POS'
  2  union all
  3  select * from tb_b where '&&prod' = 'PRE';
Enter value for prod: POS

    DEPTNO DNAME          LOC
---------- -------------- -------------
        10 ACCOUNTING     NEW YORK
        20 RESEARCH       DALLAS

SQL> undefine prod
SQL> /
Enter value for prod: PRE

    DEPTNO DNAME          LOC
---------- -------------- -------------
        30 SALES          CHICAGO
        40 OPERATIONS     BOSTON

SQL>

CodePudding user response:

You can create a function (or a procedure) which returns a record set of SYS_REFCURSOR type parameter after accepting one of your parameters (POS,PRE) no matter what structure has your tables(tb_a or tb_b) such as

CREATE OR REPLACE FUNCTION Get_tab_ab( i_prod VARCHAR2 ) RETURN SYS_REFCURSOR IS
  v_recordset  SYS_REFCURSOR;                     
  v_sql        VARCHAR2(32767);
BEGIN
  v_sql := 'SELECT * FROM '||CASE 
                             WHEN i_prod = 'POS' THEN 
                                  'tb_a' 
                             WHEN i_prod = 'PRE' THEN 
                                  'tb_b' 
                              END;
  OPEN v_recordset FOR v_sql;
  RETURN v_recordset;
END;
/

and then call from SQL Developer's console like this

SQL> DECLARE
    res SYS_REFCURSOR;
BEGIN
   :res := Get_tab_ab('POS');
END;
/

SQL> PRINT res;

or you can use a common ROWTYPE variable because the structures of the tables(tb_a or tb_b) are identical considering you are combining them with a UNION ALL operator along with FETCH..INTO clause. This time you'll directly print out the desired columns without creating a stored object such as a function or procedure, just switching the value of the variable v_prod

DECLARE
  v_recordset  SYS_REFCURSOR;
  v_rec        tb_a%ROWTYPE;
  v_sql        VARCHAR2(32767);
  v_prod       VARCHAR2(3) := 'POS';
BEGIN

  v_sql := 'SELECT * FROM '||CASE 
                             WHEN v_prod = 'POS' THEN 
                                  'tb_a' 
                             WHEN v_prod = 'PRE' THEN 
                                  'tb_b' 
                              END;
  OPEN v_recordset FOR v_sql;
  LOOP
     FETCH v_recordset INTO v_rec;
    EXIT WHEN v_recordset%NOTFOUND;
    DBMS_OUTPUT.PUT_LINE(v_rec.col1||' '||v_rec.col2||' '||v_rec.col3);
  END LOOP;
  CLOSE v_recordset;
  
END;
/
  • Related