dynamic columns in oracle using sql - sql

I have following example of table. Thera can be unlimited branch and customers. I need group this branches and count their customers, then show it's with different columns.
BRANCHNAME CUSTOMERNO
100 1001010
100 1001011
103 1001012
104 1001013
104 1001014
104 1001015
105 1001016
105 1001017
106 1001018
Note that there can be unlimited branch and customers, the query must work not only this case.
In this case the accepted result is:
100 103 104 105 106
2 1 3 2 1
Example SQL DATA
select '100' BranchName,'1001010' CustomerNo from dual UNION ALL
select '100' BranchName,'1001011' CustomerNo from dual UNION ALL
select '103' BranchName,'1001012' CustomerNo from dual UNION ALL
select '104' BranchName,'1001013' CustomerNo from dual UNION ALL
select '104' BranchName,'1001014' CustomerNo from dual UNION ALL
select '104' BranchName,'1001015' CustomerNo from dual UNION ALL
select '105' BranchName,'1001016' CustomerNo from dual UNION ALL
select '105' BranchName,'1001017' CustomerNo from dual UNION ALL
select '106' BranchName,'1001018' CustomerNo from dual

I think it is possible, though quite complicated, to write a pipelined table function that returns a variable structure. Your pipeline table function will use the Oracle Data Cartridge interface and the magic of the AnyDataSet type to return a dynamic structure at runtime. You can then use that in subsequent SQL statements as if it was a table, i.e.
SELECT *
FROM TABLE( your_pipelined_function( p_1, p_2 ));
A couple more references that discuss the same sample implementation
Dynamic SQL Pivoting
The Implementing the Interface Approach section of the Oracle Data Cartridge Developer's Guide
Method4. After downloading and installing the open source PL/SQL code, here is a complete implementation:
--Create sample table.
create table branch_data as
select '100' BranchName,'1001010' CustomerNo from dual UNION ALL
select '100' BranchName,'1001011' CustomerNo from dual UNION ALL
select '103' BranchName,'1001012' CustomerNo from dual UNION ALL
select '104' BranchName,'1001013' CustomerNo from dual UNION ALL
select '104' BranchName,'1001014' CustomerNo from dual UNION ALL
select '104' BranchName,'1001015' CustomerNo from dual UNION ALL
select '105' BranchName,'1001016' CustomerNo from dual UNION ALL
select '105' BranchName,'1001017' CustomerNo from dual UNION ALL
select '106' BranchName,'1001018' CustomerNo from dual;
--Create a dynamic pivot in SQL.
select *
from table(method4.dynamic_query(
q'[
--Create a select statement
select
--The SELECT:
'select'||chr(10)||
--The column list:
listagg(
replace(q'!sum(case when BranchName = '#BRANCH_NAME#' then 1 else 0 end) "#BRANCH_NAME#"!', '#BRANCH_NAME#', BranchName)
, ','||chr(10)) within group (order by BranchName)||chr(10)||
--The FROM:
'from branch_data' v_sql
from
(
--Distinct BranchNames.
select distinct BranchName
from branch_data
)
]'
));

If you just want to report the results somewhere, you may use a cursor for the select statement:
select branchname, count(*) from test group by branchname order by branchname asc;
Looping through the cursor you may get your values.
here is my sample:
declare
v_b varchar2(1000);
v_t varchar2(1000);
begin
for i in (select branchname, count(*) total from test group by branchname order by branchname asc)
loop
v_b := v_b || i.branchname || ' ';
v_t := v_t || i.total || ' ';
end loop;
dbms_output.put_line(v_b);
dbms_output.put_line(v_t);
end;

This will get it in rows (rather than columns):
SELECT branchname,
COUNT( DISTINCT customerno ) AS customers
FROM your_table
GROUP BY branchname;
(Note: you can omit the DISTINCT keyword if there will never be repeats of the branchname, customerno pair.)
Without knowing what the branch names are you are could only do a dynamic pivot.
It would be much simpler to take the output of the above query (in row format) and transpose it in whatever front-end you are using to access the database.
From comments:
I need a report in this format, and don't want write some application , wants to do with sql for easily export to excell in such format
No, you don't need it in column format in SQL. You can put it into excel in row format and then use excel's TRANSPOSE function to convert it (very simply) to columns without having to implement a complicated dynamic SQL solution.

What about this solution. Without no table creation, just set the v_sql parameter.
SET SERVEROUTPUT ON SIZE 100000
DECLARE
v_cursor sys_refcursor;
CURSOR get_columns
IS
SELECT EXTRACTVALUE (t2.COLUMN_VALUE, 'node()') VALUE
FROM (SELECT *
FROM TABLE (XMLSEQUENCE (v_cursor))) t1,
TABLE (XMLSEQUENCE (EXTRACT (t1.COLUMN_VALUE, '/ROW/node()'))) t2;
v_column VARCHAR2 (1000);
v_value VARCHAR2 (1000);
v_counter NUMBER (3) := 0;
v_sql VARCHAR2 (4000);
BEGIN
v_sql :=
'SELECT branchname, COUNT (DISTINCT customerno) AS customers'
|| ' FROM (SELECT 100 branchname, 1001010 customerno'
|| ' FROM DUAL'
|| ' UNION ALL'
|| ' SELECT 100 branchname, 1001011 customerno'
|| ' FROM DUAL'
|| ' UNION ALL'
|| ' SELECT 103 branchname, 1001012 customerno'
|| ' FROM DUAL'
|| ' UNION ALL'
|| ' SELECT 104 branchname, 1001013 customerno'
|| ' FROM DUAL'
|| ' UNION ALL'
|| ' SELECT 104 branchname, 1001014 customerno'
|| ' FROM DUAL'
|| ' UNION ALL'
|| ' SELECT 104 branchname, 1001015 customerno'
|| ' FROM DUAL'
|| ' UNION ALL'
|| ' SELECT 105 branchname, 1001016 customerno'
|| ' FROM DUAL'
|| ' UNION ALL'
|| ' SELECT 105 branchname, 1001017 customerno'
|| ' FROM DUAL'
|| ' UNION ALL'
|| ' SELECT 106 branchname, 1001018 customerno'
|| ' FROM DUAL)'
|| ' GROUP BY branchname';
OPEN v_cursor FOR v_sql;
FOR v_record IN get_columns
LOOP
IF v_counter = 0
THEN
v_column := v_column || v_record.VALUE || ' ';
v_counter := 1;
ELSIF v_counter = 1
THEN
v_value := v_value || v_record.VALUE || ' ';
v_counter := 0;
END IF;
END LOOP;
DBMS_OUTPUT.put_line (v_column);
DBMS_OUTPUT.put_line (v_value);
END;
/
And the output is
100 105 104 103 106
2 2 3 1 1

with src as
(select '100' BranchName,'1001010' CustomerNo from dual UNION ALL
select '100' BranchName,'1001011' CustomerNo from dual UNION ALL
select '103' BranchName,'1001012' CustomerNo from dual UNION ALL
select '104' BranchName,'1001013' CustomerNo from dual UNION ALL
select '104' BranchName,'1001014' CustomerNo from dual UNION ALL
select '104' BranchName,'1001015' CustomerNo from dual UNION ALL
select '105' BranchName,'1001016' CustomerNo from dual UNION ALL
select '105' BranchName,'1001017' CustomerNo from dual UNION ALL
select '106' BranchName,'1001018' CustomerNo from dual )
SELECT * FROM
(select BranchName from src)
PIVOT XML
(COUNT(*) FOR (BranchName)
IN
(SELECT DISTINCT BranchName FROM SRC))
This query gives the output in xml format. The whole xml data will be contained in the field that the query results(The query has only single row-sinlge column output). The next step is to parse the xml data and display it in tabular form.

You can use this selection:
SELECT branchname, count(*)
FROM test
GROUP BY branchname
In general it is not professional to use selection for every number in branchname.

Related

How to take where clause conditions from table column in oracle SQL or plsql

How to take where clause conditions from table column in oracle plsql.
E.g. data in table
Condition
1.sourceSystemId = 'SN'
2.AND(coverageType='AD',amountType1='PREMIUM',premiumFrequency='REGULAR',yearOfPremium='1')
e.g query:
select * from xyz where rule='abc' and "sourceSystemId = 'SN'"
select * from xyz where rule='abc' AND(coverageType='AD',amountType1='PREMIUM',premiumFrequency='REGULAR',yearOfPremium='1')
Not entirely sure what you're asking here, but I would imagine that
select * from xyz where rule='abc' AND(coverageType='AD',amountType1='PREMIUM',premiumFrequency='REGULAR',yearOfPremium='1')
would become
select * from xyz
where rule='abc'
AND coverageType='AD'
and amountType1='PREMIUM'
and premiumFrequency='REGULAR'
and yearOfPremium='1'
I suppose you want something like :
DECLARE
l_query VARCHAR2(2000) := 'select * from xyz where rule=''abc''';
l_result xyz%ROWTYPE;
l_cursor SYS_REFCURSOR;
BEGIN
dbms_output.put_line(l_query);
FOR clause IN (SELECT condition
FROM conditions)
LOOP
l_query := l_query||' AND '||clause.condition;
END LOOP;
OPEN l_cursor FOR l_query;
LOOP
FETCH l_cursor INTO l_result;
EXIT WHEN l_cursor%NOTFOUND;
..
-- your processing
END LOOP;
CLOSE l_cursor;
END;
Here is example of SQL solution. I used justt first and last condition but you can get them all...
WITH
xyz As
(
Select 1 "ID", 'abc' "RULE", 'AD' "COVERAGETYPE", 'PREMIUM' "AMOUNTTYPE1", 'REGULAR' "PREMIUMFREQUENCY", '1' "YEAROFPREMIUM" From Dual
UNION
Select 2 "ID", 'abc' "RULE", 'BF' "COVERAGETYPE", 'ORDINARY' "AMOUNTTYPE1", 'EXTRA' "PREMIUMFREQUENCY", '2' "YEAROFPREMIUM" From Dual
UNION
Select 3 "ID", 'abc' "RULE", 'AD' "COVERAGETYPE", 'PREMIUM' "AMOUNTTYPE1", 'REGULAR' "PREMIUMFREQUENCY", '1' "YEAROFPREMIUM" From Dual
),
conditions As
(
SELECT UPPER('coverageType=AD,amountType1=PREMIUM,premiumFrequency=REGULAR,yearOfPremium=1') "CND" From Dual
)
SELECT
x.ID, x.RULE, x.COVERAGETYPE, x.AMOUNTTYPE1, x.PREMIUMFREQUENCY, x.YEAROFPREMIUM
FROM
xyz x
INNER JOIN
conditions c ON(1=1)
WHERE
x.RULE = 'abc' And
x.COVERAGETYPE = CASE WHEN InStr(c.CND || ',', 'COVERAGETYPE=') = 0 THEN x.COVERAGETYPE
ELSE SubStr(SubStr(c.CND || ',', InStr(c.CND || ',', 'COVERAGETYPE=') + Length('COVERAGETYPE=')), 1, InStr(SubStr(c.CND || ',', InStr(c.CND || ',', 'COVERAGETYPE=') + Length('COVERAGETYPE=') + 1), ',')) END And
x.YEAROFPREMIUM = CASE WHEN InStr(c.CND || ',', 'YEAROFPREMIUM=') = 0 THEN x.YEAROFPREMIUM
ELSE SubStr(SubStr(c.CND || ',', InStr(c.CND || ',', 'YEAROFPREMIUM=') + Length('YEAROFPREMIUM=')), 1, InStr(SubStr(c.CND || ',', InStr(c.CND || ',', 'YEAROFPREMIUM=') + Length('YEAROFPREMIUM=') + 1), ',')) END
Result:
ID RULE COVERAGETYPE AMOUNTTYPE1 PREMIUMFREQUENCY YEAROFPREMIUM
1 abc AD PREMIUM REGULAR 1
3 abc AD PREMIUM REGULAR 1

ORA-01489 : result of string concatenation to long

I am creating a dynamic query from a list of tables which are their in my table called : get_table_names
My Query :
SELECT listagg('SELECT '
|| ''''
|| tbl_name
|| ''''
|| ' AS TBL , COUNT(*) as CNT FROM '
|| 'TGT_MB.'
|| tbl_name
|| ' union all'
|| CHAR(10) ) WITH GROUP ( ORDER BY tbl_name) AS sql_str
FROM get_table_names;
My get_table_names as lots of table , at least 70 table names.
The query works fine for 10 tables but more then that it throws the error like below
ORA-01489 : result of string concatenation to long
Their is some option called EXTEND that option I cannot touch as I have low level privileges.
cannot make changes to it until DBA.
Any other work around would be much appreciated like using some XMLAGG or CLOB , BLOB
Can I respectively suggest that when posting a code snippet, make it sure it runs so that people can help you more easily. eg your code above took the following debugging before we could even start to see what you want to do
SQL> SELECT listagg('SELECT '
2 || ''''
3 || table_name
4 || ''''
5 || ' AS TBL , COUNT(*) as CNT FROM '
6 || 'TGT_MB.'
7 || table_name
8 || ' union all'
9 || CHAR(10) ) WITH GROUP ( ORDER BY table_name) AS sql_str
10 FROM dba_tables
11 where owner = 'SCOTT';
|| CHAR(10) ) WITH GROUP ( ORDER BY table_name) AS sql_str
*
ERROR at line 9:
ORA-00936: missing expression
SQL> SELECT listagg('SELECT '
2 || ''''
3 || table_name
4 || ''''
5 || ' AS TBL , COUNT(*) as CNT FROM '
6 || 'TGT_MB.'
7 || table_name
8 || ' union all'
9 || chr(10) ) WITH GROUP ( ORDER BY table_name) AS sql_str
10 FROM dba_tables
11 where owner = 'SCOTT';
|| chr(10) ) WITH GROUP ( ORDER BY table_name) AS sql_str
*
ERROR at line 9:
ORA-00923: FROM keyword not found where expected
Once those fixes are done, we end up here
SQL> SELECT listagg('SELECT '
2 || ''''
3 || table_name
4 || ''''
5 || ' AS TBL , COUNT(*) as CNT FROM '
6 || 'TGT_MB.'
7 || table_name
8 || ' union all'
9 || chr(10),'' ) WITHIN GROUP ( ORDER BY table_name) AS sql_str
10 FROM dba_tables
11 where owner = 'SCOTT';
SQL_STR
-------------------------------------------------------------------------------------
SELECT 'BONUS' AS TBL , COUNT(*) as CNT FROM TGT_MB.BONUS union all
SELECT 'DEPT' AS TBL , COUNT(*) as CNT FROM TGT_MB.DEPT union all
SELECT 'EMP' AS TBL , COUNT(*) as CNT FROM TGT_MB.EMP union all
SELECT 'EMP2' AS TBL , COUNT(*) as CNT FROM TGT_MB.EMP2 union all
SELECT 'SALGRADE' AS TBL , COUNT(*) as CNT FROM TGT_MB.SALGRADE union all
which ultimately blows up when we get too many tables
SQL> SELECT listagg('SELECT '
2 || ''''
3 || table_name
4 || ''''
5 || ' AS TBL , COUNT(*) as CNT FROM '
6 || 'TGT_MB.'
7 || table_name
8 || ' union all'
9 || chr(10),'' ) WITHIN GROUP ( ORDER BY table_name) AS sql_str
10 FROM dba_tables;
FROM dba_tables
*
ERROR at line 10:
ORA-01489: result of string concatenation is too long
Now even if we use a tool (eg
https://github.com/connormcd/listagg_clob) to get the results as a clob, then I imagine you are just going to fire that SQL at the database to get a count of all tables. If that is the case, then why do you need to LISTAGG at all, just build a script to do it, ie
SELECT 'SELECT '
|| ''''
|| table_name
|| ''''
|| ' AS TBL , COUNT(*) as CNT FROM '
|| 'TGT_MB.'
|| table_name
|| ' union all'
FROM dba_tables
Spool that to a file, trim the last union all and run it as a script.
Or even better...think about what benefit the output gives you. Why does anyone need the exact row count? Querying NUM_ROWS from USER_TABLES is probably sufficient.

Oracle dynamic query (return or select) result as table

How can I show the result of running a dynamic query as a table in the output?
I want to show the result of the following query as a table in the output.
my table :
create table myTable(ROW_NAME varchar(10),COLUMN_NAME varchar(10),COLUMN_NAME_VALUE varchar(10));
table data :
insert into myTable (ROW_NAME,COLUMN_NAME,COLUMN_NAME_VALUE)
select 'ROW1','COL1','R1C1' from dual
union all select 'ROW1','COL2','R1C2' from dual
union all select 'ROW1','COL3','R1C3' from dual
union all select 'ROW2','COL1','R2C1' from dual
union all select 'ROW2','COL2','R2C2' from dual
union all select 'ROW2','COL3','R2C3' from dual
union all select 'ROW3','COL1','R3C1' from dual
union all select 'ROW3','COL2','R3C3' from dual
union all select 'ROW3','COL3','R3C3' from dual
my dynamic query :
DECLARE
mycols VARCHAR2(1000);
sqlCommand varchar2(1000);
TYPE PivotCurTyp IS REF CURSOR;
pivot_cv PivotCurTyp;
type pivotted is record (row_name myTable.row_name%type, col1 myTable.column_name_value%type, col2 myTable.column_name_value%type, col3 myTable.column_name_value%type);
piv_rec pivotted;
BEGIN
select (select LISTAGG('''' || COLUMN_NAME || '''', ',') from myTable group by ROW_NAME FETCH FIRST 1 ROWS ONLY) into mycols from dual;
select Concat('select * from myTable pivot ( max (COLUMN_NAME_VALUE) for COLUMN_NAME in (',Concat(mycols,')) ORDER BY ROW_NAME')) into sqlCommand from dual;
DBMS_OUTPUT.PUT_LINE(sqlCommand);
OPEN pivot_cv FOR sqlCommand;
LOOP
FETCH pivot_cv INTO piv_rec;
EXIT WHEN pivot_cv%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('ROW_NAME: ' || piv_rec.ROW_NAME || ' COL1: ' ||
piv_rec.COL1 || ' COL2: ' || piv_rec.COL2 || ' COL3: ' || piv_rec.COL3);
END LOOP;
CLOSE pivot_cv;
END;
/
demo in db<>fiddle
Thanks for any help
Maybe I misunderstood, I guess what you want is this?
select 'ROW_NAME ' || t1.row_name || ' ' || listagg(t1.column_name || ': ' || t1.column_name_value, ' ')
within group(order by t1.column_name)
from myTable t1
group by t1.row_name
order by t1.row_name

oracle dynamic pivot error: SQL command not properly ended

I have a table whose data is obtained according to the desired output with pivot. But I want to create the number of columns dynamically.
my table :
create table myTable(ROW_NAME varchar(10),COLUMN_NAME varchar(10),COLUMN_NAME_VALUE varchar(10));
table data :
insert into myTable (ROW_NAME,COLUMN_NAME,COLUMN_NAME_VALUE)
select 'ROW1','COL1','R1C1' from dual
union all select 'ROW1','COL2','R1C2' from dual
union all select 'ROW1','COL3','R1C3' from dual
union all select 'ROW2','COL1','R2C1' from dual
union all select 'ROW2','COL2','R2C2' from dual
union all select 'ROW2','COL3','R2C3' from dual
union all select 'ROW3','COL1','R3C1' from dual
union all select 'ROW3','COL2','R3C3' from dual
union all select 'ROW3','COL3','R3C3' from dual
my query :
select * from myTable
pivot (
max (COLUMN_NAME_VALUE)
for COLUMN_NAME
in (
'COL1' as COL1,'COL2' as COL2,'COL3' as COL3
)
)
ORDER BY ROW_NAME;
The above query works but I want to get the columns dynamically.
my dynamic query :
DECLARE
mycols VARCHAR2(1000);
sqlCommand varchar2(1000);
TYPE PivotCurTyp IS REF CURSOR;
pivot_cv PivotCurTyp;
piv_rec mytable%ROWTYPE;
BEGIN
select (select LISTAGG(COLUMN_NAME, ',') from myTable group by ROW_NAME FETCH FIRST 1 ROWS ONLY) into mycols from dual;
select Concat('select * from myTable pivot ( max (COLUMN_NAME_VALUE) for COLUMN_NAME in (',Concat(mycols,')) ORDER BY ROW_NAME;')) into sqlCommand from dual;
OPEN pivot_cv FOR sqlCommand;
LOOP
FETCH pivot_cv INTO piv_rec;
EXIT WHEN pivot_cv%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('ROW_NAME: ' || piv_rec.ROW_NAME || ' COL1: ' ||
piv_rec.COLUMN_NAME_VALUE || 'COL2: ' || piv_rec.COLUMN_NAME_VALUE || 'COL3: ' || piv_rec.COLUMN_NAME_VALUE);
END LOOP;
CLOSE pivot_cv;
END;
/
Note : The equivalent of the above query can be generated on SQL Server and I have created it.
demo in db<>fiddle
Thanks for any help
There are 3 problems in your script:
semicolon-terminated dynamic query (that's the cause of "SQL command not properly ended")
identifiers in in clause instead of string literals (you can use 'foo' or 'foo' as foo but not foo alone)
improper piv_rec type - use table format after pivot, not before pivot
Summary:
DECLARE
mycols VARCHAR2(1000);
sqlCommand varchar2(1000);
TYPE PivotCurTyp IS REF CURSOR;
pivot_cv PivotCurTyp;
type pivotted is record (row_name myTable.row_name%type, col1 myTable.column_name_value%type, col2 myTable.column_name_value%type, col3 myTable.column_name_value%type);
piv_rec pivotted;
BEGIN
select (select LISTAGG('''' || COLUMN_NAME || '''', ',') from myTable group by ROW_NAME FETCH FIRST 1 ROWS ONLY) into mycols from dual;
select Concat('select * from myTable pivot ( max (COLUMN_NAME_VALUE) for COLUMN_NAME in (',Concat(mycols,')) ORDER BY ROW_NAME')) into sqlCommand from dual;
DBMS_OUTPUT.PUT_LINE(sqlCommand);
OPEN pivot_cv FOR sqlCommand;
LOOP
FETCH pivot_cv INTO piv_rec;
EXIT WHEN pivot_cv%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('ROW_NAME: ' || piv_rec.ROW_NAME || ' COL1: ' ||
piv_rec.COL1 || ' COL2: ' || piv_rec.COL2 || ' COL3: ' || piv_rec.COL3);
END LOOP;
CLOSE pivot_cv;
END;
/
updated db fiddle (BTW composing fiddle was very motivating to help)

dynamic table name in select statement

I have a series of history tables in an oracle 9 database. History_table_00 contains last months data, History_table_01 contains the month before, and History_table_02 the month before that. Next month, History_table_02 will automatically get renamed to history_table_03, history_table_01 renamed to history_table_02, history_table_00 renamed to history_table_01, and a new history_table_00 will be created to gather the newest history (I really hope I am making sense).
Anyway, I need to write a select statement that will dynamically select all history tables. I am hoping this won't be too complicated because they all share the same name, just appended with sequential number so I can discover the table names with:
select table_name from all_tables where table_name like 'HISTORY_TABLE_%';
My standard query for each table is going to be:
select id, name, data_column_1, data_column_2 from history_table_%;
What do I have to do to accomplish the goal of writing a sql statement that will always select from all history tables without me needing to go in every month and add the new table? Thanks for anything you guys can provide.
you can use ref cursor but i wouldn't recommend it.
it goes like this
create table tab_01 as select 1 a , 10 b from dual;
create table tab_02 as select 2 a , 20 b from dual;
create table tab_03 as select 3 a , 30 b from dual;
create or replace function get_all_history
return sys_refcursor
as
r sys_refcursor;
stmt varchar2(32000);
cursor c_tables is
select table_name
from user_tables
where table_name like 'TAB_%';
begin
for x in c_tables loop
stmt := stmt || ' select * from ' || x.table_name ||' union all';
end loop;
stmt := substr(stmt , 1 , length(stmt) - length('union all'));
open r for stmt;
return r;
end;
/
SQL> select get_all_history() from dual;
GET_ALL_HISTORY()
--------------------
CURSOR STATEMENT : 1
CURSOR STATEMENT : 1
A B
---------- ----------
1 10
2 20
3 30
I would suggest you to define a view in which you select from all history tables using union all
and each time the tables are renamed you modify the view as well.
create OR replace view history_data as
SELECT id, name, data_column_1, data_column_2 FROM history_table_01
union all
SELECT id, name, data_column_1, data_column_2 FROM history_table_02
union all
SELECT id, name, data_column_1, data_column_2 FROM history_table_03
;
then you can simle SELECT * FROM history_data;
you can build the view dynamicaly with the help of the following statment:
SELECT 'SELECT id, name, data_column_1, data_column_2 FROM ' || table_name || ' union all '
FROM user_tables
WHERE table_name like 'HISTORY_TABLE_%'
The best idea is to do a dynamic SQL statement that builds up a large query for each table existing in the database. Give the following SQL query try. (please forgive my formatting, I am not sure how to do line-breaks on here)
DECLARE #table VARCHAR(255)
, #objectID INT
, #selectQuery VARCHAR(MAX)
SELECT #objectID = MIN(object_id)
FROM sys.tables
WHERE name LIKE 'history_table_%'
WHILE #objectID IS NOT NULL
BEGIN
SELECT #table = name
FROM sys.tables
WHERE object_id = #objectID
ORDER BY object_id
SELECT #selectQuery = ISNULL(#selectQuery + ' UNION ALL ', '') + 'select id, name, data_column_1, data_column_2 FROM ' + #table
SELECT #objectID = MIN(object_id)
FROM sys.tables
WHERE name LIKE 'tblt%'
AND object_id > #objectID
END
SELECT #selectQuery
--EXEC (#selectQuery)
A Possible Solution:
CREATE OR REPLACE PROCEDURE GET_HIST_DETAILS IS
DECLARE
QUERY_STATEMENT VARCHAR2(4000) := NULL;
CNT NUMBER;
BEGIN
select COUNT(table_name) INTO CNT from all_tables where table_name like 'HISTORY_TABLE_%';
FOR loop_counter IN 1..CNT
LOOP
IF LOOP_COUNTER <> CNT THEN
{
QUERY_STATEMENT := QUERY_STATEMENT || 'select id, name, data_column_1, data_column_2 from history_table_0' || loop_counter || ' UNION';
}
ELSE
{
QUERY_STATEMENT := QUERY_STATEMENT || 'select id, name, data_column_1, data_column_2 from history_table_0' || loop_counter ;
}
EXECUTE_IMMEDIATE QUERY_STATEMENT;
END LOOP;
END GET_DETAILS;
PS:I dont have Oracle installed , so havent tested it for syntax errors.