Convert string from a table to be used as a column for selection for another table - sql

I have a table where I store records to be used as a column name for my queries where the record is an actual column on another table.
TBL_1
COL_1
==========
SAMPLE_COL
TBL_2
SAMPLE_COL_1 SAMPLE_COL2
============ ===========
ABC DEF
I'm having a problem using the record that I fetched to use as an actual column. I already tried a bunch of things like casting and using case (using case works but it's a bit of a brute force and I'm looking for a more elegant way of doing this).
This is a sample query that I have tried:
SELECT (SELECT column_1 FROM tbl_1)
FROM tbl_2
Expected output
SAMPLE_COL_1
============
ABC
Actual output
(SELECT column_1 FROM tbl_1)
============================
SAMPLE_COL_1
This is what I've tried that worked so far but a brute force technique
SELECT (
CASE
WHEN (SELECT column_1 FROM tbl_2) = 'SAMPLE_COL_1' THEN SAMPLE_COL_1
ELSE SAMPLE_COL_2
END
)
FROM tbl_2
Appreciate the help! Keep safe from COVID-19 everyone :)

It's not that easy as you'd want it to be - you'll have to use dynamic SQL. Here's an example, based on Scott's table(s).
Create a function that accepts table and column names and returns ref cursor.
SQL> create or replace function f_test
2 (par_table_name in varchar2, par_column_name in varchar2)
3 return sys_refcursor
4 is
5 rc sys_refcursor;
6 begin
7 open rc for 'select ' || dbms_assert.simple_sql_name(par_column_name) ||
8 ' from ' || dbms_assert.sql_object_name(par_table_name);
9 return rc;
10 end;
11 /
Function created.
Testing:
SQL> select f_test('dept', 'dname') from dual;
F_TEST('DEPT','DNAME
--------------------
CURSOR STATEMENT : 1
CURSOR STATEMENT : 1
DNAME
--------------
ACCOUNTING
RESEARCH
SALES
OPERATIONS
SQL> select f_test('dual', 'dummy') from dual;
F_TEST('DUAL','DUMMY
--------------------
CURSOR STATEMENT : 1
CURSOR STATEMENT : 1
D
-
X
SQL>
Another example, with column (and table) names stored in a table (something like you posted).
Table that contains those info and the function:
SQL> select * from tbl_1;
TNAM CNAME
---- -----
dept dname
dual dummy
SQL> create or replace function f_test
2 (par_table_name in varchar2)
3 return sys_refcursor
4 is
5 l_str varchar2(1000);
6 rc sys_refcursor;
7 begin
8 select 'select ' || dbms_assert.simple_sql_name(cname) ||
9 ' from ' || dbms_assert.sql_object_name(tname)
10 into l_str
11 from tbl_1
12 where tname = dbms_assert.sql_object_name(par_table_name);
13 open rc for l_str;
14 return rc;
15 end;
16 /
Function created.
Testing:
SQL> select f_test('dept') from dual;
F_TEST('DEPT')
--------------------
CURSOR STATEMENT : 1
CURSOR STATEMENT : 1
DNAME
--------------
ACCOUNTING
RESEARCH
SALES
OPERATIONS
SQL>

Related

How to dynamically construct table name

I would like to construct a query where a table name is based off of another table's column mod 12. For example:
SELECT *
FROM table_b_XX
where XX here is determined by table_a.column_a % 12.
Presuming you have such a tables:
SQL> create table table_a as
2 select 1212 as column_a from dual;
Table created.
As the following result returns 0, we need table_b_00 so I'll create it:
SQL> select mod(1212, 12) from dual;
MOD(1212,12)
------------
0
SQL> create table table_b_00 as select 'table 00' name from dual;
Table created.
SQL> create table table_b_01 as select 'table 01' name from dual;
Table created.
Now, create a function which returns ref cursor; it selects rows from a table whose name is designed by the help of the table_a contents:
SQL> create or replace function f_test return sys_refcursor
2 is
3 l_str varchar2(200);
4 rc sys_refcursor;
5 begin
6 select 'select * from table_b_' || lpad(mod(a.column_a, 12), 2, '0')
7 into l_str
8 from table_a a;
9
10 open rc for l_str;
11 return rc;
12 end f_test;
13 /
Function created.
Let's try it:
SQL> select f_test from dual;
F_TEST
--------------------
CURSOR STATEMENT : 1
CURSOR STATEMENT : 1
NAME
--------
table 00
Right; that's contents of table_b_00.
Consider the following meta code:
DECLARE
n VARCHAR2(32767);
r VARCHAR2(32767);
BEGIN
SELECT column_a INTO name FROM table_a;
EXECUTE IMMEDIATE 'SELECT r FROM table_b_'||n INTO r;
END;
/

INSERT INTO TAB SELECT * FROM TABLE TAB#db2 - Too many values

I'm trying to move rows between two tables which have many columns.
The table columns are identical other than the destination table (tab#db2) has a few more columns which causes a simple INSERT to fail.
I'd like to use a simple PL/SQL statement to build a list of the columns in tab#db2 dynamically instead of typing out the names of col1, col2, etc in the INSERT and SELECT clause. Example
declare a variable as var_col_list
set col_list = output of select * from tab (omitting rows)
INSERT INTO TAB *var_col_list* SELECT *var_cols_list* FROM TABLE TAB#db2
I've researched using %rowtype but cannot find a suitable example that would take less time than simply writing out the names of the columns!
Any advice is greatly appreciated
If you use e.g. TOAD, you can right-click the table and let it Generate statement - in your case, that would be INSERT. You'd slightly modify it (remove columns you don't need) and that's all.
Otherwise, this is how you might do it semi-manually.
This is my source table:
SQL> SELECT * FROM dept;
DEPTNO DNAME LOC
---------- -------------------- --------------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
Target table doesn't contain all columns:
SQL> CREATE TABLE target
2 (
3 deptno NUMBER,
4 dname VARCHAR2 (20)
5 );
Table created.
Code which loops through all TARGET table columns (i.e. a table which has less columns) and composes the INSERT INTO statement:
SQL> DECLARE
2 l_str VARCHAR2 (1000);
3 BEGIN
4 FOR cur_r IN (SELECT column_name
5 FROM user_tab_columns
6 WHERE table_name = 'TARGET')
7 LOOP
8 l_str := l_str || ', ' || cur_r.column_name;
9 END LOOP;
10
11 l_str :=
12 'insert into target select ' || LTRIM (l_str, ', ') || ' from dept';
13 DBMS_OUTPUT.put_line (l_str);
14
15 EXECUTE IMMEDIATE l_str;
16 END;
17 /
insert into target select DEPTNO, DNAME from dept --> this is the L_STR contents
PL/SQL procedure successfully completed.
SQL> SELECT * FROM target;
DEPTNO DNAME
---------- --------------------
10 ACCOUNTING
20 RESEARCH
30 SALES
40 OPERATIONS
Seems to be OK.
Using the solution provided by Littefoot, I made some minor tweaks to fit my requirement perfectly:
SQL> create table taba (col1 number,col2 number);
SQL> insert into taba values (1,2);
SQL> select * from taba;
COL1 COL2
---------- ----------
1 2
SQL> create table tabb (col1 number,col2 number, col3 number);
SQL> DECLARE
l_str VARCHAR2 (32767);
BEGIN
FOR cur_r IN (SELECT column_name
FROM user_tab_columns
WHERE table_name = 'TABA'
order by column_id asc)
LOOP
l_str := l_str || ', ' || cur_r.column_name;
END LOOP;
l_str :=
'insert into tabb (' || LTRIM (l_str, ', ') || ') ' ||' select ' || LTRIM (l_str, ', ') || ' from taba';
DBMS_OUTPUT.put_line (l_str);
EXECUTE IMMEDIATE l_str;
END;
/
Output of l_str (SQL INSERT):
insert into tabb (COL1, COL2) select COL1, COL2 from taba
Result:
SQL> select * from tabb;
COL1 COL2 COL3
---------- ---------- ----------
1 2

How to use a dynamic variable created using INTO within a new query using IN clause under where condition in PL/SQL

DECLARE
l_filter varchar2(100);
BEGIN
SELECT filter INTO l_filter
FROM dashboard
WHERE id=TARGET_ID_1;
I get l_filter as ('016','018','011','014') from this. Now i want to use this l_filter values within IN clause in the query below dynamically.
select a,b from grid
where filter_value in l_filter;
How can I do this in PL/SQL?
You could use regular expressions:
select g.a, g.b
from grid g
where exists (select 1
from dashboard d.
where d.id = TARGET_ID_1 and
regexp_like(d.filter_value, '^(' || replace(d.filter, '''', ''), ',', '|') || ')$')
);
This is not particularly efficient, but it does not require any PL/SQL or dynamic SQL.
That said, you might want to store your "filters" as rows in a table so you can just join things together, dispensing with the complication.
Use LIKE:
DECLARE
l_filter varchar2(100);
cur SYS_REFCURSOR;
a GRID.A%TYPE;
b GRID.B%TYPE;
BEGIN
SELECT filter
INTO l_filter
FROM dashboard
WHERE id = TARGET_ID_1;
OPEN cur FOR
SELECT a,b
FROM grid
WHERE ','||SUBSTR(l_filter,2,LENGTH(l_filter)-2)||',' LIKE '%,'''||filter_value||''',%';
LOOP
FETCH cur INTO a,b;
EXIT WHEN cur%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(a || ', ' || b);
END LOOP;
CLOSE cur;
END;
/
db<>fiddle here
Here's how I understood the question.
Sample data first:
SQL> select * from dashboard;
ID FILTER
---------- -----------------------
1 '016','018','011','014'
2 '111', '222'
SQL> select * from grid;
A B FIL
---------- ---------- ---
100 200 016
101 201 011
200 400 xxx
SQL>
Function that returns refcursor; the key (in this example) is to split filter values into rows so that you could use them as a subquery (lines #15 - 18):
SQL> create or replace function f_get (target_id_1 in dashboard.id%type)
2 return sys_refcursor
3 is
4 l_filter varchar2(100);
5 rc sys_refcursor;
6 begin
7 select filter
8 into l_filter
9 from dashboard
10 where id = target_id_1;
11
12 open rc for
13 select g.a, g.b
14 from grid g
15 where g.filter_value in (select regexp_substr(replace(l_filter, chr(39), ''), '[^,]+', 1, level)
16 from dual
17 connect by level <= regexp_count(l_filter, ',') + 1
18 );
19
20 return rc;
21 end;
22 /
Function created.
Testing:
SQL> select f_get(1) from dual;
F_GET(1)
--------------------
CURSOR STATEMENT : 1
CURSOR STATEMENT : 1
A B
---------- ----------
100 200
101 201
SQL>

pl-sql errror on select HR schema

i want to do something like that.. but in a function.. select * from employees where employee_id = &employee_id in HR schema of oracle
Q: Create Function “SEARCH_EMPLOYEE” that receives an Employee ID and returns all its attributes through an output parameter with a data structure that represents all its information
R:
Create or replace FUNCTION get_complete_employee (&in_employee_id IN NUMBER)
AS person_details;
BEGIN
SELECT * --'Name-'||first_name||' '|| last_name
into person_details
FROM employees;
Dbms_output.put_line(person_details);
-- END get_complete_employee;
end;
i have a error of sintax i guess..
i don't know what is wrong
If you are learning how to create the function which returns entire row of the table then following is the basic example of doing the same:
Table data:
SQL> select * from EMP;
EMP_ID EMP_NAME E
---------- -------------------- -
10 John N
20 May Y
SQL>
Function:
SQL> CREATE OR REPLACE FUNCTION GET_COMPLETE_EMPLOYEE (
2 IN_EMPLOYEE_ID IN NUMBER
3 ) RETURN EMP%ROWTYPE AS
4 MY_ROWTYPE EMP%ROWTYPE;
5 BEGIN
6 SELECT
7 * --'Name-'||first_name||' '|| last_name
8 INTO MY_ROWTYPE
9 FROM
10 EMP
11 WHERE
12 EMP_ID = IN_EMPLOYEE_ID;
13
14 RETURN MY_ROWTYPE;
15 END;
16 /
Function created.
SQL>
Calling the function and result:
SQL> SET SERVEROUT ON
SQL>
SQL> DECLARE
2 EMPTYPE EMP%ROWTYPE;
3 BEGIN
4 EMPTYPE := GET_COMPLETE_EMPLOYEE(10);
5 DBMS_OUTPUT.PUT_LINE(EMPTYPE.EMP_NAME);
6 END;
7 /
John
You must have to handle multiple exception scenarios in real-world coding.
Cheers!!

Is it possible to pass a table name to a SQL query by select query in oracle

Is it possible to pass a table name to a query using a result of another query?
SELECT T.MID, T.TID, M.NAME
FROM 'ONLINETRANSACTION#(' || SELECT ONLINEDBLINK FROM PARAMETERTABLE ||')' T
LEFT JOIN 'ONLINEMERCHANT#(' || SELECT ONLINEDBLINK FROM PARAMETERTABLE ||')' M
ON T.MID = M.MID
I have tried with the above code but it doesn't work.
This is a simple example based on Scott's schema.
lines 5 - 7 select your "table name" (actually, it appears that it is a database link name in your code. Doesn't matter, the principle is just the same)
line 9 uses that "table name" and concatenates it with the rest of the SELECT statement; finally, it executes it using EXECUTE IMMEDIATE
SQL> create table param (table_name varchar2(30));
Table created.
SQL> insert into param values ('EMP');
1 row created.
SQL> set serveroutput on
SQL> declare
2 l_table_name param.table_name%type;
3 l_max_sal emp.sal%type;
4 begin
5 select table_name into l_table_name
6 from param
7 where rownum = 1;
8
9 execute immediate 'select max(sal) from ' || l_table_name into l_max_sal;
10 dbms_output.put_line('Max salary = ' || l_max_sal);
11 end;
12 /
Max salary = 10000
PL/SQL procedure successfully completed.
SQL>