Oracle searching a case insensive CLOB - oracle

I have some code that searches a CLOB, which works fine. I'm attempting to wrap it in a function that I found online so the search can be CASE insensitive but I am running into some syntax errors and was hoping someone could help me out.
Below is my test CASE. I'm using livesql in can anyone wants to emulate my environment. Thanks in advance to all who answer.
create or replace type se_obj is object (s number, e number);
/
create or replace type se_tbl is table of se_obj;
/
create or replace function search_clob(p_lob clob, p_what varchar2)
return se_tbl
pipelined
as
len int := length(p_what);
s int;
pos int := 1;
begin
if p_lob is not null then
loop
s := instr(p_lob, p_what, pos);
exit when s = 0;
pipe row (se_obj(s, s + len - 1));
pos := s + len;
end loop;
end if;
return;
end;
/
CREATE OR REPLACE FUNCTION upper_clob(p_clob CLOB) RETURN CLOB
AS
v_clob CLOB; -- TEMPORARY CLOB TO WRITE TO
v_posn NUMBER := 1; -- CURRENT POSITION WITHIN CLOB
v_holder VARCHAR2(4000); -- CHARACTER STRING HOLDER
BEGIN
dbms_lob.createtemporary(v_clob,TRUE,dbms_lob.CALL);
WHILE (v_posn < dbms_lob.getlength(p_clob)) LOOP
v_holder := dbms_lob.substr(p_clob,4000,v_posn);
v_posn := v_posn + 4000;
v_holder := upper(v_holder);
dbms_lob.write(v_clob, length(v_holder),v_posn,v_holder);
END LOOP;
return v_clob;
end;
/
create table t ( x int primary key, y clob );
-- works fine
select t.x id, l.s start_pos, l.e end_pos, dbms_lob.getlength(y) clob_len
from t outer apply search_clob(y, 'hello world') l where l.s > 0
-- getting a syntax error
select t.x id, l.s start_pos, l.e end_pos, dbms_lob.getlength(y) clob_len
from t outer apply search_clob(upper_lob
(y), 'HELLO WORLD') l where l.s > 0

It's really overkill to call pl/sql functions for such purposes when you can easily achieve it in SQL...
Simple SQL example:
https://dbfiddle.uk/?rdbms=oracle_18&fiddle=13fa9071bd6ad34ebbf5fd6de4907a34
Test data:
create table t ( x int primary key, y clob );
insert into t
select
level,
to_clob('x')
||rpad(' ',4000,' ')||to_char(level,'0000')
||rpad(' ',4000,' ')||to_char(level,'0000')
||rpad(' ',4000,' ')||to_char(level,'0000')
as y
from dual
connect by level<=30;
commit;
Simple query:
select
x,
length(y) clob_len,
s.*
from t
outer apply(
select
nullif(instr(lower(t.y), :subs, 1, level),0) start_pos
,nullif(instr(lower(t.y), :subs, 1, level),0) + length('1') as end_pos
from dual
connect by instr(lower(t.y), :subs, 1, level)>0
) s
Or using modern SQL Macro: (tested on Oracle 19.11)
CREATE OR REPLACE FUNCTION search_clob(input_clob clob, search_string varchar2) return varchar2 SQL_MACRO is
BEGIN
RETURN q'{
select
nullif(instr(lower(search_clob.input_clob), search_clob.search_string, 1, level),0) start_pos
,nullif(instr(lower(search_clob.input_clob), search_clob.search_string, 1, level),0)
+ length(search_clob.search_string) as end_pos
from dual
connect by instr(lower(search_clob.input_clob), search_clob.search_string, 1, level)>0
}';
END;
/
select
x,
length(y) clob_len,
s.*
from t
outer apply search_clob(t.y, '1') s
Example using the first query:
SQL> var subs varchar2(10);
SQL> exec :subs:='1';
PL/SQL procedure successfully completed.
SQL> select
2 x,
3 length(y) clob_len,
4 s.*
5 from t
6 outer apply(
7 select
8 nullif(instr(lower(t.y), :subs, 1, level),0) start_pos
9 ,nullif(instr(lower(t.y), :subs, 1, level),0) + length('1') as end_pos
10 from dual
11 connect by instr(lower(t.y), :subs, 1, level)>0
12 ) s;
X CLOB_LEN START_POS END_POS
---------- ---------- ---------- ----------
1 12016 4006 4007
1 12016 8011 8012
1 12016 12016 12017
2 12016
3 12016
4 12016
5 12016
6 12016
7 12016
8 12016
9 12016
10 12016 4005 4006
10 12016 8010 8011
10 12016 12015 12016
11 12016 4005 4006
11 12016 4006 4007
11 12016 8010 8011
11 12016 8011 8012
11 12016 12015 12016
11 12016 12016 12017
12 12016 4005 4006
12 12016 8010 8011
12 12016 12015 12016
13 12016 4005 4006
13 12016 8010 8011
13 12016 12015 12016
14 12016 4005 4006
14 12016 8010 8011
14 12016 12015 12016
15 12016 4005 4006
15 12016 8010 8011
15 12016 12015 12016
16 12016 4005 4006
16 12016 8010 8011
16 12016 12015 12016
17 12016 4005 4006
17 12016 8010 8011
17 12016 12015 12016
18 12016 4005 4006
18 12016 8010 8011
18 12016 12015 12016
19 12016 4005 4006
19 12016 8010 8011
19 12016 12015 12016
20 12016
21 12016 4006 4007
21 12016 8011 8012
21 12016 12016 12017
22 12016
23 12016
24 12016
25 12016
26 12016
27 12016
28 12016
29 12016
30 12016
57 rows selected.

Related

Print Next Line When Error Occurs

Using exception I need to print the next value after an error occurred.
For example
FOR i IN 1..50
IF MOD(i,5) <> 0 THEN
dbms_output.put_line(i);
I need to print all values except values divisible by 5.
Thanks in advance.
If this would be code in pl/sql then you are very close - just try to add: BEGIN, LOOP, END IF, END LOOP and END clauses:
begin
FOR i IN 1..50 LOOP
IF MOD(i,5) <> 0 THEN
dbms_output.put_line(i);
end if;
end loop;
end;
/
1
2
3
4
6
7
8
9
11
12
13
14
16
17
18
19
21
22
23
24
26
27
28
29
31
32
33
34
36
37
38
39
41
42
43
44
46
47
48
49

Split data in 2 groups in Matlab with both groups having all unique ids

I am trying to split a data set into 2 groups such that both groups have all unique ids present at least once. The data set is something like
01 02 03 04 05 06 07
07 05 08 09 10 11 12
01 04 07 13 08 14 15
06 10 11 12 08 01 02
13 14 10 01 07 03 02
15 01 03 04 10 13 11
11 12 03 05 07 14 15
06 05 10 13 01 09 14
I am trying to use Matlab to split it in 2 roughly equal groups such that both groups have at least one row where the unique ids (in this case 01 - 15) are present at least once. Will appreciate any help in getting this done.
The data has to be divided in a way that entire row has to belong to either group 1 or group 2. I am looking at my output to be 2 matrices such that
01 02 03 04 05 06 07
07 05 08 09 10 11 12
01 04 07 13 08 14 15
06 10 11 12 08 01 02
and
13 14 10 01 07 03 02
15 01 03 04 10 13 11
11 12 03 05 07 14 15
06 05 10 13 01 09 14
are the 2 output groups.
01 02 03 04 05 06 07 is row 1. 07 05 08 09 10 11 12 is row 2 and so on. Each row has 7 ids. There are 8 different rows. I want to divide it in 2 groups such that both groups will have 5/4 rows each (minor variations dont matter). Position of ids in each row cant be changed. Each row has to be sent as whole into group 1 or 2 but the row structure (position of each id in that row) has to remain intact. All unique ids need to be present in both groups.
script
clear;clc
A = [01 02 03 04 05 06 07;
07 05 08 09 10 11 12;
01 04 07 13 08 14 15;
06 10 11 12 08 01 02;
13 14 10 01 07 03 02;
15 01 03 04 10 13 11;
11 12 03 05 07 14 15;
06 05 10 13 01 09 14];
% find unique elements and rows containing them
UniqElem = unique(A);
NUniqElem = length(UniqElem);
UniqIndex = struct('UniqElem', cell(NUniqElem,1), ...
'UniqRows', cell(NUniqElem, 1), 'RowCount', cell(NUniqElem, 1));
for ii = 1:NUniqElem
t1 = UniqElem(ii);
t2 = find(any(A==t1,2));
UniqIndex(ii).UniqRows = t2;
UniqIndex(ii).UniqElem = t1;
UniqIndex(ii).RowCount = length(t2);
end
clear('t1','t2')
% find all possible combinations to make the first group
Combs1 = testf(UniqIndex);
Combs2 = struct('Combination', Combs1, ...
'Unique', {true});
for ii = 1:(length(Combs2)-1)
if Combs2(ii).Unique
CurrentComb = Combs2(ii).Combination;
for jj = (ii+1):length(Combs2)
if Combs2(jj).Unique && ...
all(ismember(CurrentComb,Combs2(jj).Combination))
Combs2(jj).Unique = false;
end
end
end
end
Combs3 = Combs2([Combs2.Unique]);
Combs4 = struct('Grp1', {Combs3.Combination}, 'Grp2', []);
AllRows = 1:size(A,1);
for ii = 1:length(Combs4)
Combs4(ii).Grp2 = AllRows(~ismember(AllRows, Combs4(ii).Grp1));
end
Combs5 = struct('Grp1', [], 'Grp2', []);
for ii = 1:length(Combs4)
if all(ismember(UniqElem, unique(A([Combs4(ii).Grp2], :))))
Combs5(end+1) = Combs4(ii);
end
end
Combinations = Combs5;
for ii = 1:length(Combinations)
fprintf('Solution %d of %d \n', ii, length(Combinations))
CurrentComb = Combinations(ii);
fprintf('Group 1 \n')
for jj = 1:length(CurrentComb.Grp1)
fprintf('R%2d: %s \n', CurrentComb.Grp1(jj), ...
num2str(A(CurrentComb.Grp1(jj), :), '%-4d') )
end
fprintf('Group 2 \n')
for jj = 1:length(CurrentComb.Grp2)
fprintf('R%2d: %s \n', CurrentComb.Grp2(jj), ...
num2str(A(CurrentComb.Grp2(jj), :), '%-4d') )
end
fprintf('\n')
end
function
function Comb = testf(UniqRowIn)
if length(UniqRowIn) == 1
Comb = num2cell(UniqRowIn.UniqRows)';
else
t2 = testf(UniqRowIn(2:end));
t1 = UniqRowIn(1).UniqRows;
Comb = cell(0);
for ii = 1:length(t2)
CurrentComb = t2{ii};
if isempty(intersect(CurrentComb, t1))
for jj = 1:length(t1)
Comb{end+1,1} = sort([CurrentComb, t1(jj)]);
end
else
Comb{end+1,1} = CurrentComb;
end
end
end
end
output
Solution 1 of 12
Group 1
Group 2
Solution 2 of 12
Group 1
R 1: 1 2 3 4 5 6 7
R 2: 7 5 8 9 10 11 12
R 3: 1 4 7 13 8 14 15
Group 2
R 4: 6 10 11 12 8 1 2
R 5: 13 14 10 1 7 3 2
R 6: 15 1 3 4 10 13 11
R 7: 11 12 3 5 7 14 15
R 8: 6 5 10 13 1 9 14
Solution 3 of 12
Group 1
R 3: 1 4 7 13 8 14 15
R 4: 6 10 11 12 8 1 2
R 5: 13 14 10 1 7 3 2
R 8: 6 5 10 13 1 9 14
Group 2
R 1: 1 2 3 4 5 6 7
R 2: 7 5 8 9 10 11 12
R 6: 15 1 3 4 10 13 11
R 7: 11 12 3 5 7 14 15
Solution 4 of 12
Group 1
R 3: 1 4 7 13 8 14 15
R 4: 6 10 11 12 8 1 2
R 6: 15 1 3 4 10 13 11
R 8: 6 5 10 13 1 9 14
Group 2
R 1: 1 2 3 4 5 6 7
R 2: 7 5 8 9 10 11 12
R 5: 13 14 10 1 7 3 2
R 7: 11 12 3 5 7 14 15
Solution 5 of 12
Group 1
R 3: 1 4 7 13 8 14 15
R 4: 6 10 11 12 8 1 2
R 7: 11 12 3 5 7 14 15
R 8: 6 5 10 13 1 9 14
Group 2
R 1: 1 2 3 4 5 6 7
R 2: 7 5 8 9 10 11 12
R 5: 13 14 10 1 7 3 2
R 6: 15 1 3 4 10 13 11
Solution 6 of 12
Group 1
R 1: 1 2 3 4 5 6 7
R 3: 1 4 7 13 8 14 15
R 7: 11 12 3 5 7 14 15
R 8: 6 5 10 13 1 9 14
Group 2
R 2: 7 5 8 9 10 11 12
R 4: 6 10 11 12 8 1 2
R 5: 13 14 10 1 7 3 2
R 6: 15 1 3 4 10 13 11
Solution 7 of 12
Group 1
R 1: 1 2 3 4 5 6 7
R 2: 7 5 8 9 10 11 12
R 5: 13 14 10 1 7 3 2
R 6: 15 1 3 4 10 13 11
Group 2
R 3: 1 4 7 13 8 14 15
R 4: 6 10 11 12 8 1 2
R 7: 11 12 3 5 7 14 15
R 8: 6 5 10 13 1 9 14
Solution 8 of 12
Group 1
R 2: 7 5 8 9 10 11 12
R 4: 6 10 11 12 8 1 2
R 5: 13 14 10 1 7 3 2
R 6: 15 1 3 4 10 13 11
Group 2
R 1: 1 2 3 4 5 6 7
R 3: 1 4 7 13 8 14 15
R 7: 11 12 3 5 7 14 15
R 8: 6 5 10 13 1 9 14
Solution 9 of 12
Group 1
R 4: 6 10 11 12 8 1 2
R 5: 13 14 10 1 7 3 2
R 6: 15 1 3 4 10 13 11
R 8: 6 5 10 13 1 9 14
Group 2
R 1: 1 2 3 4 5 6 7
R 2: 7 5 8 9 10 11 12
R 3: 1 4 7 13 8 14 15
R 7: 11 12 3 5 7 14 15
Solution 10 of 12
Group 1
R 1: 1 2 3 4 5 6 7
R 2: 7 5 8 9 10 11 12
R 6: 15 1 3 4 10 13 11
R 7: 11 12 3 5 7 14 15
Group 2
R 3: 1 4 7 13 8 14 15
R 4: 6 10 11 12 8 1 2
R 5: 13 14 10 1 7 3 2
R 8: 6 5 10 13 1 9 14
Solution 11 of 12
Group 1
R 4: 6 10 11 12 8 1 2
R 6: 15 1 3 4 10 13 11
R 7: 11 12 3 5 7 14 15
R 8: 6 5 10 13 1 9 14
Group 2
R 1: 1 2 3 4 5 6 7
R 2: 7 5 8 9 10 11 12
R 3: 1 4 7 13 8 14 15
R 5: 13 14 10 1 7 3 2
Solution 12 of 12
Group 1
R 1: 1 2 3 4 5 6 7
R 2: 7 5 8 9 10 11 12
R 5: 13 14 10 1 7 3 2
R 7: 11 12 3 5 7 14 15
Group 2
R 3: 1 4 7 13 8 14 15
R 4: 6 10 11 12 8 1 2
R 6: 15 1 3 4 10 13 11
R 8: 6 5 10 13 1 9 14
>>

return resultset from function

I need to return a resultset from function and work with this resultset just like with an ordinary table.
So I need something like following:
select * from table(querydb('select * from dual'))
The querydb function should return a resultset of a query passed to it.
Can it be implemented in oracle?
Would be grateful for any information.
If you need a result set and a ref cursor won't do with a datatype called sys.anydataset. i.e what you seem to want is a pipelined function, but of course with a regular pipelined function you need to define the output structure, which in your case isn't static.
Enter anydataset. this type allows us to dynamically generate types on the fly (at hard parse time only) to allow us to define pipelined functions with varying outputs.
The coding is a bit complex unfortunately.
To start with, we define a type that will do the processing of the passed in SQL statement.
SQL> create type dyn_pipeline as object
2 (
3 atype anytype,
4
5 static function ODCITableDescribe(rtype out anytype,
6 stmt in varchar2)
7 return number,
8
9 static function ODCITablePrepare(sctx out dyn_pipeline,
10 tf_info in sys.ODCITabfuncinfo,
11 stmt in varchar2)
12 return number,
13
14 static function ODCITableStart(sctx in out dyn_pipeline,
15 stmt in varchar2)
16 return number,
17
18 member function ODCITablefetch(self in out dyn_pipeline,
19 nrows in number,
20 rws out anydataset)
21 return number,
22
23 member function ODCITableClose(self in dyn_pipeline)
24 return number
25 );
26 /
Next up, we create a package spec that will be basically your querydb function call:
SQL> create package pkg_pipeline
2 as
3
4 /*
5 * Global Types
6 */
7 -- Describe array.
8 type dynamic_sql_rec is record(cursor integer,
9 column_cnt pls_integer,
10 description dbms_sql.desc_tab2,
11 execute integer);
12 -- Meta data for the ANYTYPE.
13 type anytype_metadata_rec is record(precision pls_integer,
14 scale pls_integer,
15 length pls_integer,
16 csid pls_integer,
17 csfrm pls_integer,
18 schema varchar2(30),
19 type anytype,
20 name varchar2(30),
21 version varchar2(30),
22 attr_cnt pls_integer,
23 attr_type anytype,
24 attr_name varchar2(128),
25 typecode pls_integer);
26
27
28 /*
29 * Global Variables
30 */
31 -- SQL descriptor.
32 r_sql dynamic_sql_rec;
33
34 /*
35 * function will run the given SQL
36 */
37 function querydb(p_stmt in varchar2)
38 return anydataset pipelined using dyn_pipeline;
39
40 end pkg_pipeline;
41 /
Package created.
the types there will just hold some info about the SQL structure itself (we will be using DBMS_SQL to describe the input SQL as it has functions to get the number of columns, data types etc out of any given SQL statement.
The main type body is where the processing occurs:
SQL> create type body dyn_pipeline
2 as
3
4 /*
5 * DESC step. this will be called at hard parse and will create
6 * a physical type in the DB Schema based on the select columns.
7 */
8 static function ODCITableDescribe(rtype out anytype,
9 stmt in varchar2)
10 return number
11 is
12
13 /* Variables */
14 -- Type to hold the dbms_sql info (description)
15 r_sql pkg_pipeline.dynamic_sql_rec;
16 -- Type to create (has all the columns) of the sql query.
17 t_anyt anytype;
18 -- SQL query that will be made up from the 2 passed in queries.
19 v_sql varchar2(32767);
20
21 begin
22
23 /*
24 * Parse the SQL and describe its format and structure.
25 */
26 v_sql := replace(stmt, ';', null);
27
28 -- open, parse and discover all info about this SQL.
29 r_sql.cursor := dbms_sql.open_cursor;
30 dbms_sql.parse( r_sql.cursor, v_sql, dbms_sql.native );
31 dbms_sql.describe_columns2( r_sql.cursor, r_sql.column_cnt, r_sql.description );
32 dbms_sql.close_cursor( r_sql.cursor );
33
34 -- Start to create the physical type.
35 anytype.BeginCreate( DBMS_TYPES.TYPECODE_OBJECT, t_anyt );
36
37 -- Loop through each attribute and add to the type.
38 for i in 1 .. r_sql.column_cnt
39 loop
40
41 t_anyt.AddAttr(r_sql.description(i).col_name,
42 case
43 when r_sql.description(i).col_type in (1,96,11,208)
44 then dbms_types.typecode_varchar2
45 when r_sql.description(i).col_type = 2
46 then dbms_types.typecode_number
47 when r_sql.description(i).col_type in (8,112)
48 then dbms_types.typecode_clob
49 when r_sql.description(i).col_type = 12
50 then dbms_types.typecode_date
51 when r_sql.description(i).col_type = 23
52 then dbms_types.typecode_raw
53 when r_sql.description(i).col_type = 180
54 then dbms_types.typecode_timestamp
55 when r_sql.description(i).col_type = 181
56 then dbms_types.typecode_timestamp_tz
57 when r_sql.description(i).col_type = 182
58 then dbms_types.typecode_interval_ym
59 when r_sql.description(i).col_type = 183
60 then dbms_types.typecode_interval_ds
61 when r_sql.description(i).col_type = 231
62 then dbms_types.typecode_timestamp_ltz
63 end,
64 r_sql.description(i).col_precision,
65 r_sql.description(i).col_scale,
66 r_sql.description(i).col_max_len,
67 r_sql.description(i).col_charsetid,
68 r_sql.description(i).col_charsetform );
69 end loop;
70
71 t_anyt.EndCreate;
72
73 -- set the output type to our built type.
74 ANYTYPE.BeginCreate(dbms_types.TYPECODE_TABLE, rtype);
75 rtype.SetInfo(null, null, null, null, null, t_anyt,
76 dbms_types.TYPECODE_OBJECT, 0);
77 rtype.EndCreate();
78
79 return ODCIConst.Success;
80
81 end ODCITableDescribe;
82
83
84 /*
85 * PREPARE step. Initialise our type.
86 */
87 static function ODCITableprepare(sctx out dyn_pipeline,
88 tf_info in sys.ODCITabfuncinfo,
89 stmt in varchar2)
90 return number
91 is
92
93 /* Variables */
94 -- Meta data.
95 r_meta pkg_pipeline.anytype_metadata_rec;
96
97 begin
98
99 r_meta.typecode := tf_info.rettype.getattreleminfo(
100 1, r_meta.precision, r_meta.scale, r_meta.length,
101 r_meta.csid, r_meta.csfrm, r_meta.type, r_meta.name
102 );
103
104 sctx := dyn_pipeline(r_meta.type);
105 return odciconst.success;
106
107 end;
108
109
110 /*
111 * START step. this is where we execute the cursor prior to fetching from it.
112 */
113 static function ODCITablestart(sctx in out dyn_pipeline,
114 stmt in varchar2)
115 return number
116 is
117
118 /* Variables */
119 r_meta pkg_pipeline.anytype_metadata_rec;
120 v_sql varchar2(32767);
121 begin
122
123 v_sql := replace(stmt, ';', null);
124 pkg_pipeline.r_sql.cursor := dbms_sql.open_cursor;
125 dbms_sql.parse(pkg_pipeline.r_sql.cursor, v_sql, dbms_sql.native);
126 dbms_sql.describe_columns2(pkg_pipeline.r_sql.cursor,
127 pkg_pipeline.r_sql.column_cnt,
128 pkg_pipeline.r_sql.description);
129
130 -- define all the columns found to let Oracle know the datatypes.
131 for i in 1..pkg_pipeline.r_sql.column_cnt
132 loop
133
134 r_meta.typecode := sctx.atype.GetAttrElemInfo(
135 i, r_meta.precision, r_meta.scale, r_meta.length,
136 r_meta.csid, r_meta.csfrm, r_meta.type, r_meta.name
137 );
138
139 case r_meta.typecode
140 when dbms_types.typecode_varchar2
141 then
142 dbms_sql.define_column(pkg_pipeline.r_sql.cursor, i, '', 32767);
143 when dbms_types.typecode_number
144 then
145 dbms_sql.define_column(pkg_pipeline.r_sql.cursor, i, cast(null as number));
146 when dbms_types.typecode_date
147 then
148 dbms_sql.define_column(pkg_pipeline.r_sql.cursor, i, cast(null as date));
149 when dbms_types.typecode_raw
150 then
151 dbms_sql.define_column_raw(pkg_pipeline.r_sql.cursor, i, cast(null as raw), r_meta.length);
152 when dbms_types.typecode_timestamp
153 then
154 dbms_sql.define_column(pkg_pipeline.r_sql.cursor, i, cast(null as timestamp));
155 when dbms_types.typecode_timestamp_tz
156 then
157 dbms_sql.define_column(pkg_pipeline.r_sql.cursor, i, cast(null as timestamp with time zone));
158 when dbms_types.typecode_timestamp_ltz
159 then
160 dbms_sql.define_column(pkg_pipeline.r_sql.cursor, i, cast(null as timestamp with local time zone));
161 when dbms_types.typecode_interval_ym
162 then
163 dbms_sql.define_column(pkg_pipeline.r_sql.cursor, i, cast(null as interval year to month));
164 when dbms_types.typecode_interval_ds
165 then
166 dbms_sql.define_column(pkg_pipeline.r_sql.cursor, i, cast(null as interval day to second));
167 when dbms_types.typecode_clob
168 then
169 case pkg_pipeline.r_sql.description(i).col_type
170 when 8
171 then
172 dbms_sql.define_column_long(pkg_pipeline.r_sql.cursor, i);
173 else
174 dbms_sql.define_column(pkg_pipeline.r_sql.cursor, i, cast(null as clob));
175 end case;
176 end case;
177 end loop;
178
179 -- execute the SQL.
180 pkg_pipeline.r_sql.execute := dbms_sql.execute(pkg_pipeline.r_sql.cursor);
181
182 return odciconst.success;
183
184 end ODCITablestart;
185
186
187 /*
188 * FETCH step.
189 */
190 member function ODCITablefetch(self in out dyn_pipeline,
191 nrows in number,
192 rws out anydataset)
193 return number
194 is
195
196 /* Variables */
197 -- Buffers to hold values.
198 v_vc_col varchar2(32767);
199 v_num_col number;
200 v_date_col date;
201 v_raw_col raw(32767);
202 v_raw_error number;
203 v_raw_len integer;
204 v_int_ds_col interval day to second;
205 v_int_ym_col interval year to month;
206 v_ts_col timestamp;
207 v_tstz_col timestamp with time zone;
208 v_tsltz_col timestamp with local time zone;
209 v_clob_col clob;
210 v_clob_offset integer := 0;
211 v_clob_len integer;
212 -- Metadata
213 r_meta pkg_pipeline.anytype_metadata_rec;
214
215 begin
216
217 if dbms_sql.fetch_rows( pkg_pipeline.r_sql.cursor ) > 0
218 then
219
220 -- Describe to get number and types of columns.
221 r_meta.typecode := self.atype.getinfo(
222 r_meta.precision, r_meta.scale, r_meta.length,
223 r_meta.csid, r_meta.csfrm, r_meta.schema,
224 r_meta.name, r_meta.version, r_meta.attr_cnt
225 );
226
227 anydataset.begincreate(dbms_types.typecode_object, self.atype, rws);
228 rws.addinstance();
229 rws.piecewise();
230
231 -- loop through each column extracting value.
232 for i in 1..pkg_pipeline.r_sql.column_cnt
233 loop
234
235 r_meta.typecode := self.atype.getattreleminfo(
236 i, r_meta.precision, r_meta.scale, r_meta.length,
237 r_meta.csid, r_meta.csfrm, r_meta.attr_type,
238 r_meta.attr_name
239 );
240
241 case r_meta.typecode
242 when dbms_types.typecode_varchar2
243 then
244 dbms_sql.column_value(pkg_pipeline.r_sql.cursor, i, v_vc_col);
245 rws.setvarchar2(v_vc_col);
246 when dbms_types.typecode_number
247 then
248 dbms_sql.column_value(pkg_pipeline.r_sql.cursor, i, v_num_col);
249 rws.setnumber(v_num_col);
250 when dbms_types.typecode_date
251 then
252 dbms_sql.column_value(pkg_pipeline.r_sql.cursor, i, v_date_col);
253 rws.setdate(v_date_col);
254 when dbms_types.typecode_raw
255 then
256 dbms_sql.column_value_raw(pkg_pipeline.r_sql.cursor, i, v_raw_col,
257 v_raw_error, v_raw_len);
258 rws.setraw(v_raw_col);
259 when dbms_types.typecode_interval_ds
260 then
261 dbms_sql.column_value(pkg_pipeline.r_sql.cursor, i, v_int_ds_col);
262 rws.setintervalds(v_int_ds_col);
263 when dbms_types.typecode_interval_ym
264 then
265 dbms_sql.column_value(pkg_pipeline.r_sql.cursor, i, v_int_ym_col);
266 rws.setintervalym(v_int_ym_col);
267 when dbms_types.typecode_timestamp
268 then
269 dbms_sql.column_value(pkg_pipeline.r_sql.cursor, i, v_ts_col);
270 rws.settimestamp(v_ts_col);
271 when dbms_types.typecode_timestamp_tz
272 then
273 dbms_sql.column_value(pkg_pipeline.r_sql.cursor, i, v_tstz_col);
274 rws.settimestamptz(v_tstz_col);
275 when dbms_types.typecode_timestamp_ltz
276 then
277 dbms_sql.column_value(pkg_pipeline.r_sql.cursor, i, v_tsltz_col);
278 rws.settimestampltz(v_tsltz_col);
279 when dbms_types.typecode_clob
280 then
281 case pkg_pipeline.r_sql.description(i).col_type
282 when 8
283 then
284 loop
285 dbms_sql.column_value_long(pkg_pipeline.r_sql.cursor, i, 32767, v_clob_offset,
286 v_vc_col, v_clob_len);
287 v_clob_col := v_clob_col || v_vc_col;
288 v_clob_offset := v_clob_offset + 32767;
289 exit when v_clob_len < 32767;
290 end loop;
291 else
292 dbms_sql.column_value(pkg_pipeline.r_sql.cursor, i, v_clob_col);
293 end case;
294 rws.setclob(v_clob_col);
295 end case;
296 end loop;
297
298 rws.endcreate();
299
300 end if;
301
302 return ODCIConst.Success;
303
304 end;
305
306 /*
307 * CLOSE step. close the cursor.
308 */
309 member function ODCITableClose(self in dyn_pipeline)
310 return number
311 is
312
313
314 begin
315 dbms_sql.close_cursor( pkg_pipeline.r_sql.cursor );
316 pkg_pipeline.r_sql := null;
317 return odciconst.success;
318 end ODCITableClose;
319
320 end;
321 /
Type body created.
once this is done, you can query like:
SQL> select * from table(pkg_pipeline.querydb('select * from dual'));
D
-
X
SQL> select * from table(pkg_pipeline.querydb('select * from v$mystat where rownum <= 2'));
SID STATISTIC# VALUE
---------- ---------- ----------
230 0 1
230 1 1
If I understand you correctly, you want to do this:
select * from (select * from dual)
...with the caveat that the subquery is in some way dynamic? You can do this using a PL/SQL block, using a reference cursor:
declare
subQuery varchar2(1000);
mainQuery varchar2(1000) := 'select * from (';
type myRefCursor is ref cursor;
myResultset myRefCursor;
myField1 FIELDTYPE;
...
myFieldN FIELDTYPE;
begin
-- Generate this dynamically
subQuery := 'select * from dual';
-- Create main query and open cursor
mainQuery := mainQuery || subQuery || ')';
open myResultset for mainQuery;
-- Loop through records
loop
fetch myResultset into myField1, ..., myFieldN;
exit when myResultset%NOTFOUND;
-- Do something with the record data
dbms_output.put_line(myField1 || ' ... ' || myFieldN);
end loop;
close myResultset;
end;
/
Note that rather than using fetch into with individual variables, you can populate an entire record at once, provided you can define the record's field types. That is, if you have created a custom type or your record's type matches a table you already have in your schema. For the latter, you can use:
myRecord someTable%ROWTYPE;
...in the declaration block, then change the fetch into statement to:
fetch myResultset into myRecord;
...and access record fields using dot notation (e.g., myRecord.some_field_name).
You say in your comments that the dynamic SQL bit is from the results of some other query. Therefore, in my example code, you could use a regular cursor to loop over these data to create the subQuery variable in each instance... Although, incidentally, is there any reason why what you're trying to achieve can't be done with a simple join?

oracle analytics how to return this rows

I am writing this query for DWH purpose.
SELECT
YEAR
,MONTH
,WEEK
,C.CPG_PK CPG
,C.DEP_PK DEPT
,T.CUST_ID CUST_ID
,D1.R_ID R_ID
,Decode(d2.AT_CODE,'3',FUNC1.GET_ATT(d2.AT_CODE,D2.VAL_CODE)) AS P1
,decode(d2.AT_CODE,'2',FUNC1.GET_ATT(d2.AT_CODE,D2.VAL_CODE)) AS IC
,decode(d2.AT_CODE,'1',FUNC1.GET_ATT(d2.AT_CODE,D2.VAL_CODE)) AS B1
,decode(FUNC1.GET_ATT(d2.AT_CODE,D2.VAL_CODE), 2 , d2.AT_CODE) AS P2
,decode(FUNC1.GET_ATT(d2.AT_CODE,D2.VAL_CODE), 5 , d2.AT_CODE) AS B2
,COUNT(DISTINCT A.CUST_ID) TOTAL_ACC
,COUNT(DISTINCT T.TXN_PK) TOTAL_TXN
,SUM(AM_AMOUNT) TOTAL_AMT
FROM T_HEADER T
,CUST_MASTER A
,TX_DETAILS1 D1
,TX_DETAILS2 D2
,CPG_MASTER C
WHERE A.TYPE = 0
AND T.CUST_ID = A.CUST_ID
AND T.TXN_PK= 5001
AND T.TXN_PK= D1.TXN_PK
AND T.TXN_PK= D2.TXN_PK
AND D1.CPG_PK = C.CPG_PK
AND D1.OP = 1
GROUP BY
YEAR
,MONTH
,WEEK
,C.CPG_PK
,C.DEP_PK
,t.CUST_ID
,D1.R_ID
,Decode(d2.AT_CODE,'3',FUNC1.GET_ATT(d2.AT_CODE,D2.VAL_CODE))
,decode(d2.AT_CODE,'2',FUNC1.GET_ATT(d2.AT_CODE,D2.VAL_CODE))
,decode(d2.AT_CODE,'1',FUNC1.GET_ATT(d2.AT_CODE,D2.VAL_CODE))
,decode(FUNC1.GET_ATT(d2.AT_CODE,D2.VAL_CODE), 2 , d2.AT_CODE)
,decode(FUNC1.GET_ATT(d2.AT_CODE,D2.VAL_CODE), 5 , d2.AT_CODE)
the generated output as follows
YEAR MONTH WEEK CPG DEPT CUST_ID R_ID P1 IC B1 P2 B2 TOTAL_ACC TOTAL_TXN TOTAL_AMT
2012 08 32 127 -1 10019 3665 134 1 1
2012 08 32 127 -1 10019 3665 135 1 1
2012 08 32 127 -1 10019 3665 723 1 1
2012 08 32 127 -1 10019 3665 714 1 1
2012 08 32 127 -1 10019 3665 21 1 1
2012 08 32 128 -1 10019 3665 134 1 1
2012 08 32 128 -1 10019 3665 135 1 1
2012 08 32 128 -1 10019 3665 723 1 1
2012 08 32 128 -1 10019 3665 714 1 1
2012 08 32 128 -1 10019 3665 21 1 1
here the values are repeating i tried with possible group by.
the required ouput is
YEAR MONTH WEEK CPG DEPT CUST_ID R_ID P1 IC B1 P2 B2 TOTAL_ACC TOTAL_TXN TOTAL_AMT
2012 08 32 127 -1 10019 3665 21 714 723 134 1 1
2012 08 32 127 -1 10019 3665 21 714 723 135 1 1
2012 08 32 128 -1 10019 3665 21 714 723 134 1 1
2012 08 32 128 -1 10019 3665 21 714 723 135 1 1
the main thing is year,month,week,cpg,dept,cust_id,r_id ,p1,ic,b1,p2,b2 it should be unique row. Is it achievable using analytical functions or do I need to write pl/sql
Saw this, and I think I have an answer for you. So what you are wanting is SQL to take a table that looks like:
Year Col_1 Col_2 Col_3
2012 A
2012 B
2012 C
And transform it into:
Year Col_1 Col_2 Col_3
2012 A B C
What you can do (for the above example) is the following:
Select
Year,
Max(Col_1) as C1,
Max(Col_2) as C2,
Max(Col_3) as C3
From
Table_1
Group By
Year
This will work with out trouble if you ONLY have 1 record in each. Otherwise, you might have to figure out if you need to use MAX, MIN, SUM, or an alternative aggregation function.
If all the data was in one column and you wanted it in one column, you could use a similar technique:
Table_1
Year Col_1
2012 A
2012 B
2012 C
Code
Select
Year,
Max(Case When Col_1 = 'A' Then 'A' End) as A_Col,
Max(Case When Col_1 = 'B' Then 'B' End) as B_Col,
Max(Case When Col_1 = 'C' Then 'C' End) as C_Col
From
Table_1
Group By
Year
Note that Decodes should work in place of Case statements, but I think Cases are easier to read.

Strange SQL CE Finalize Error occuring on WP7 Application

Frame Image Function Offset
0 coredll.dll xxx_RaiseException 19
1 mscoree3_7.dll 436488
2 mscoree3_7.dll 386545
3 mscoree3_7.dll 540936
4 TransitionStub 0
5 System.Data.SqlServerCe.ConStringUtil.ReplaceDataDirectory 0
6 System.Data.SqlServerCe.SqlCeConnection.RemoveCachedMemoryUsage 64
7 System.Data.SqlServerCe.SqlCeConnection.ReleaseNativeInterfaces 488
8 System.Data.SqlServerCe.SqlCeConnection.Dispose 372
9 System.Data.SqlServerCe.SqlCeConnection.Finalize 64
10 mscoree3_7.dll 429164
11 mscoree3_7.dll 143533
12 mscoree3_7.dll 143225
13 mscoree3_7.dll 236605
14 mscoree3_7.dll 305995
15 coredll.dll ThreadBaseFunc 144
All calls to the SQL CE db are wrapped in Usings to ensure the object disposes properly. I've found nothing on the web that exlains what is happening.
Can anyone explain what is going on here?

Resources