This solution at first glance it looks complicated, but generally resolves any range. Solve problem with VALUEs which may be interfered with any other range.
Firstly create sample table and insert data:
create table test_table (col_START NUMBER, col_END NUMBER, col_MAP CHAR(1));
insert into test_table(col_START, col_END, col_MAP) values(1,10,'A');
insert into test_table(col_START, col_END, col_MAP) values(11,15,'B');
insert into test_table(col_START, col_END, col_MAP) values(5,12,'C');
Now data look like this:
START | END | MAP
1 | 10 | A
11 | 15 | B
5 | 12 | C
Now create object type:
CREATE TYPE SampleType AS OBJECT
(
id number,
map_string varchar2(2000)
)
/
CREATE TYPE SampleTypeSet AS TABLE OF SampleType
/
And also create PIPELINED FUNCTION:
CREATE OR REPLACE FUNCTION GET_DATA RETURN SampleTypeSet
PIPELINED
IS
l_one_row SampleType := SampleType(NULL, NULL);
BEGIN
FOR cur_data IN (select col_START, col_END, col_MAP from test_table) LOOP
FOR i IN cur_data.col_START..cur_data.col_END LOOP
l_one_row.id := i;
l_one_row.map_string := cur_data.col_MAP;
PIPE ROW(l_one_row);
END LOOP;
END LOOP;
RETURN;
END GET_DATA;
/
Finally you can use simple query:
SELECT * FROM TABLE(GET_DATA());
Or create and select it from view (if you want hide OBJECT implementation):
CREATE VIEW VIEW_ALL_DATA AS SELECT * FROM TABLE(GET_DATA());
SELECT * FROM VIEW_ALL_DATA;
Based on this my article:
http://martin-mares.cz/2010/08/oracle-db-pipelined-function/