Collection in PLSQL
Hi All,
I would like to use collect (or array) to maintain some pre-defined values, which can be used later in the PLSQL. Here is what I have: ORA-00932: Inconsistent datatypes: expected NUMBER....
Any idea?
Thanks in advance,
Mike
Create Table testCase
caseNbr NUMBER(5);
caseTxt VARCHAR2(10);
TYPE testMap IS TABLE OF NUMBER;
v_map testMap := testMap(1,3,5,7);
SELECT *
FROM testCase
WHERE caseNbr IN (v_map);
Edited by: user550903 on 29-Sep-2011 11:10 AM
You must declare type in SQL:
SQL> CREATE TYPE testMap IS TABLE OF NUMBER
2 /
Type created.Now you can use MEMBER OF:
SQL> declare
2 v_map testMap := testMap(10,20);
3 begin
4 for v_rec in
SQL> select deptno,
2 ename from emp
3 where deptno member of testMap(10,20)
4 /
DEPTNO ENAME
20 SMITH
20 JONES
10 CLARK
20 SCOTT
10 KING
20 ADAMS
20 FORD
10 MILLER
8 rows selected.
SQL> Or TABLE operator:
SQL> select deptno,
2 ename from emp
3 where deptno in (select * from table(testMap(10,20)))
4 /
DEPTNO ENAME
10 MILLER
10 KING
10 CLARK
20 FORD
20 ADAMS
20 SCOTT
20 JONES
20 SMITH
8 rows selected.
SQL> SY.
Similar Messages
-
How to improve performance using bulk collects with plsql tables or arrays
Hi All,
my procedure is like this
declare
cursor c1 is select ----------------------
begin
assigning to variables
validations on that variables
--50 validations are here --
insert into a table
end;
we have created indexes on primary keys,
i want to use
DECLARE
CURSOR a_cur IS
SELECT program_id
FROM airplanes;
TYPE myarray IS TABLE OF a_cur%ROWTYPE;
cur_array myarray;
BEGIN
OPEN a_cur;
LOOP
FETCH a_cur BULK COLLECT INTO cur_array LIMIT 100;
***---------can i assign cursor data to the plsql table variables or array***
***validate on the pl sql variable as---***
i
nsert into a table
EXIT WHEN a_cur%NOTFOUND;
END LOOP;
CLOSE a_cur;
END;
Edited by: Veekay on Oct 21, 2011 4:28 AMFastest way often is this:
insert /*+append */
into aTable
select * from airplanes;
commit;The select and insert part can even be done in parallel if needed.
However if the oparation is complex or the dataset is very very very very very large or the programmer is decent but not excellent then the bulk approach should be considered. It is often a pretty stable and linear scaling approach.
The solution depends a little on the database version.
LOOP
FETCH a_cur BULK COLLECT INTO cur_array LIMIT 100;
EXIT WHEN a_cur.count = 0;
forall i in a_cur.first.. a_cur.last
insert into aTable (id)
values (a_cur(i));
END LOOP;
...If you have more then one column then you might need a single collection for each column. Other possibilities depend on the db version.
Also: do not exit using a_cur%NOTFOUND. This is wrong! You might loose records from the end of the data set. -
Problem Collection of Collection with plsql
declare
TYPE t_a is record (
x VARCHAR2(32767),
w number
TYPE t_a_dtl IS VARRAY (10000) OF t_a;
TYPE t_b is record (
y varchar2(10),
z t_a_dtl
TYPE t_b_dtl IS VARRAY (10000) OF t_b;
i number := 1;
ii number := 1;
p_b t_b_dtl := t_b_dtl();
begin
p_b.extend(1);
p_b(i).z.extend(1);
p_b(i).y := 'celio';
p_b(i).z(ii).x := 'item1';
-- p_b(i).z(ii).w := 1;
-- ii := ii+1;
-- p_b(i).z(ii).x := 'item2';
-- p_b(i).z(ii).w := 2;
end;
declare
ERROR at line 1:
ORA-06531: Reference to uninitialized collection
ORA-06512: at line 23am i missing somthing? it is working for me
SQL> select * from v$version
2 ;
BANNER
Oracle9i Enterprise Edition Release 9.2.0.8.0 - 64bit Production
PL/SQL Release 9.2.0.8.0 - Production
CORE 9.2.0.8.0 Production
TNS for HPUX: Version 9.2.0.8.0 - Production
NLSRTL Version 9.2.0.8.0 - Production
SQL> DECLARE
2 TYPE t_a IS RECORD (
3 x VARCHAR2 (32767),
4 w NUMBER
5 );
6
7 TYPE t_a_dtl IS VARRAY (10000) OF t_a;
8
9 TYPE t_b IS RECORD (
10 y VARCHAR2 (10),
11 z t_a_dtl
12 );
13
14 TYPE t_b_dtl IS VARRAY (10000) OF t_b;
15
16 i NUMBER := 1;
17 ii NUMBER := 1;
18 p_b t_b_dtl := t_b_dtl ();
19 BEGIN
20 --
21 p_b.EXTEND (1);
22 p_b (i).z.EXTEND (1);
23 p_b (i).y := 'celio';
24 p_b (i).z (ii).x := 'item1';
25 DBMS_OUTPUT.put_line(p_b (i).z (ii).x);
26 END;
27 /
item1
PL/SQL procedure successfully completed. -
Apex_application.g_fXX and collection problem
Hello all!
In the midst of writing my second apex application, it appears I need to use apex_application functionality to meet my requirements and am seeking assistance.
I have a table/report with a column link (item_id) and a second column (as a text field) (there are more columns displayed), but I think they are irrelevant to this situation) populated with a value QTY (c002) from a collection where c001 = item_id. What I'm attempting to do is allow someone to enter a qty in the c002 text field, apply the qty change to the collection and reload the page displaying the new quantity value in the report when the column link (image) is selected (page redirects to itself).
Since it appears that column links are not a SUBMIT, I've put my collection update plsql in a before header process. According to the debug output, this collection insert is executed long before the rendering of the report.
This is my report plsql;
declare
l_query varchar2(4000) := '';
begin
l_query := 'select i.INVENTORY_ID, col.c002, ql.QUANTITY_AVAILABLE, i.STRAIN_CODE, i.STRAIN_NAME, i.GENOTYPE, i.AGE, i.SEX, ql.ROOM_NUMBER from SM_INVENTORY i, SM_QUANTITY_LOCATION ql, apex_collections col where ql.STRAIN_ID = i.STRAIN_ID(+) and col.collection_name (+)= ''ORDER'' and col.c001 (+)= i.INVENTORY_ID';
end;
This is my update collection plsql (I don't have the insert part yet, but my collection already contains values);
declare col_item_count number;
col_seq number;
item_id number;
qty number;
begin
if apex_collection.collection_exists('ORDER') = FALSE then
apex_collection.create_collection( p_collection_name => 'ORDER');
commit;
end if;
for i in 1..apex_application.g_f01.count
loop
item_id := apex_application.g_f01(i);
qty := apex_application.g_f02(i);
select count(c001),seq_id into col_item_count, col_seq
from apex_collections
where c001 = item_id
and collection_name = 'ORDER';
group by c001, seq_id;
if col_item_count > 0 then
apex_collection.update_member(
p_collection_name => 'ORDER',
p_seq => col_seq,
p_c001 => item_id,
p_c002 => qty);
commit;
end if;
end loop;
end;
Given all this, my collection entry is not updated with the new value of c002 displayed in my report text field.
Be advised, I've not found documentation about the apex_application package of sufficient detail to allow me to comprehend exactly what gets put into the apex_application.g_fXX values or when, but based on what I've gathered from examples/blogs, I think it contains the report in the currently rendered page, but I honestly don't know.
Given my assumptions, I'm expecting apex_application.g_f01(1) would be the first row item_id of my report and apex_application.g_f01(2) would be the first row c002 (qty from my collection) of my report. If this is correct, I would expect this would work.
What might I have missed?
Thanks!
Paul
PS. Honestly, is this methodology the only/easiest way to get my requirement/functionality to work? Is there an easier way?OK, tried this - not yet successful. This is what I've got.
Classic report loaded by;
declare
l_query varchar2(4000) := '';
begin
l_query := 'select i.INVENTORY_ID, i.INVENTORY_ID inv_id_hold, col.c002, ql.QUANTITY_AVAILABLE, i.STRAIN_CODE, i.STRAIN_NAME, i.GENOTYPE, i.AGE, i.SEX, ql.ROOM_NUMBER from SM_INVENTORY i, SM_QUANTITY_LOCATION ql, apex_collections col where ql.STRAIN_ID = i.STRAIN_ID(+) and col.collection_name (+)= ''ORDER'' and col.c001 (+)= i.INVENTORY_ID';
end;
Created a "SAVE" button.
Set up column inv_id_hold as a hidden tab form element and col.c002 as a text field tab form element (item_id and qty respectively). These should now be available as apex_application.g_f01 and apex_application.g_f02 (right?).
I have this post submit plsql in a process conditioned to the "SAVE" button.
declare col_item_count number;
col_seq number;
item_id number;
qty number;
begin
if apex_collection.collection_exists('ORDER') = FALSE then
apex_collection.create_collection( p_collection_name => 'ORDER');
end if;
for i in 1..apex_application.g_f01.count
loop
item_id := apex_application.g_f01(i);
qty := apex_application.g_f02(i);
select count(c001),seq_id into col_item_count, col_seq
from apex_collections
where c001 = apex_application.g_f01(i)
and collection_name = 'ORDER';
--group by c001, seq_id;*
if col_item_count > 0 then
apex_collection.update_member(
p_collection_name => 'ORDER',
p_seq => col_seq,
p_c001 => item_id,
p_c002 => qty);
else
apex_collection.add_member(
p_collection_name => 'ORDER',
p_c001 => item_id,
p_c002 => qty);
end if;
end loop;
end;
When I enter something in my qty column and press SAVE, I get "ORA-01403: no data found" being thrown by the plsql process (per debug). Since everything is going on "under the hood" and there is no step debugger in apex, I'm not able to see/understand the process in action and determine where the problem is occurring.
I got the idea for all of this here - http://apex.oracle.com/pls/otn/f?p=39839:3:5596350954563087::NO which is the shopping cart page of the online store application. But I'm trying to get the quantity edit portion to work on the inventory listing (so a customer can add items to an order simply by providing qty input for a particular line item(s) and saving).
Any advice?
Can you write an order processing system in apex that uses a collection to store line items? -
Can I use Bulk Collect results as input parameter for another cursor
MUSIC ==> remote MUSIC_DB database, MUSIC table has 60 million rows
PRICE_DATA ==> remote PRICING_DB database, PRICE_DATE table has 1 billion rows
These two table once existed in same database, but size of database exceeded available hardware size and hardware budget, so the PRICE_DATA table was moved to another Oracle database. I need to create a single report that combines data from both of these tables, and a distributed join with DRIVING_SITE hint will not work because the size of both table is too large to push to one DRIVING_SITE location, so I wrote this PLSQL block to process in small blocks.
QUESTION: how can use bulk collect from one cursor and pass that bulk collected information as input to second cursor without specifically listing each cell of the PLSQL bulk collection? See sample pseudo-code below, I am trying to determine more efficient way to code than hard-coding 100 parameter names into 2nd cursor.
NOTE: below is truly pseudo-code, I had to change the names of everything to adhere to NDA, but below works and is fast enough for my purposes, but if I want to change from 100 input parameters to 200, I have to add more hard-coded values. There has got to be a better way.
DECLARE
-- define cursor that retrieves distinct SONG_IDs from MUSIC table in remote music database
CURSOR C_CURRENT_MUSIC
IS
select distinct SONG_ID
from MUSIC@MUSIC_DB
where PRODUCTION_RELEASE=1
/* define a parameterized cursor that accepts 100 SONG_IDs and retrieves
required pricing information
CURSOR C_get_music_price_data
P_SONG_ID_001 NUMBER, P_SONG_ID_002 NUMBER, P_SONG_ID_003 NUMBER, P_SONG_ID_004 NUMBER, P_SONG_ID_005 NUMBER, P_SONG_ID_006 NUMBER, P_SONG_ID_007 NUMBER, P_SONG_ID_008 NUMBER, P_SONG_ID_009 NUMBER, P_SONG_ID_010 NUMBER,
P_SONG_ID_011 NUMBER, P_SONG_ID_012 NUMBER, P_SONG_ID_013 NUMBER, P_SONG_ID_014 NUMBER, P_SONG_ID_015 NUMBER, P_SONG_ID_016 NUMBER, P_SONG_ID_017 NUMBER, P_SONG_ID_018 NUMBER, P_SONG_ID_019 NUMBER, P_SONG_ID_020 NUMBER,
P_SONG_ID_021 NUMBER, P_SONG_ID_022 NUMBER, P_SONG_ID_023 NUMBER, P_SONG_ID_024 NUMBER, P_SONG_ID_025 NUMBER, P_SONG_ID_026 NUMBER, P_SONG_ID_027 NUMBER, P_SONG_ID_028 NUMBER, P_SONG_ID_029 NUMBER, P_SONG_ID_030 NUMBER,
P_SONG_ID_031 NUMBER, P_SONG_ID_032 NUMBER, P_SONG_ID_033 NUMBER, P_SONG_ID_034 NUMBER, P_SONG_ID_035 NUMBER, P_SONG_ID_036 NUMBER, P_SONG_ID_037 NUMBER, P_SONG_ID_038 NUMBER, P_SONG_ID_039 NUMBER, P_SONG_ID_040 NUMBER,
P_SONG_ID_041 NUMBER, P_SONG_ID_042 NUMBER, P_SONG_ID_043 NUMBER, P_SONG_ID_044 NUMBER, P_SONG_ID_045 NUMBER, P_SONG_ID_046 NUMBER, P_SONG_ID_047 NUMBER, P_SONG_ID_048 NUMBER, P_SONG_ID_049 NUMBER, P_SONG_ID_050 NUMBER,
P_SONG_ID_051 NUMBER, P_SONG_ID_052 NUMBER, P_SONG_ID_053 NUMBER, P_SONG_ID_054 NUMBER, P_SONG_ID_055 NUMBER, P_SONG_ID_056 NUMBER, P_SONG_ID_057 NUMBER, P_SONG_ID_058 NUMBER, P_SONG_ID_059 NUMBER, P_SONG_ID_060 NUMBER,
P_SONG_ID_061 NUMBER, P_SONG_ID_062 NUMBER, P_SONG_ID_063 NUMBER, P_SONG_ID_064 NUMBER, P_SONG_ID_065 NUMBER, P_SONG_ID_066 NUMBER, P_SONG_ID_067 NUMBER, P_SONG_ID_068 NUMBER, P_SONG_ID_069 NUMBER, P_SONG_ID_070 NUMBER,
P_SONG_ID_071 NUMBER, P_SONG_ID_072 NUMBER, P_SONG_ID_073 NUMBER, P_SONG_ID_074 NUMBER, P_SONG_ID_075 NUMBER, P_SONG_ID_076 NUMBER, P_SONG_ID_077 NUMBER, P_SONG_ID_078 NUMBER, P_SONG_ID_079 NUMBER, P_SONG_ID_080 NUMBER,
P_SONG_ID_081 NUMBER, P_SONG_ID_082 NUMBER, P_SONG_ID_083 NUMBER, P_SONG_ID_084 NUMBER, P_SONG_ID_085 NUMBER, P_SONG_ID_086 NUMBER, P_SONG_ID_087 NUMBER, P_SONG_ID_088 NUMBER, P_SONG_ID_089 NUMBER, P_SONG_ID_090 NUMBER,
P_SONG_ID_091 NUMBER, P_SONG_ID_092 NUMBER, P_SONG_ID_093 NUMBER, P_SONG_ID_094 NUMBER, P_SONG_ID_095 NUMBER, P_SONG_ID_096 NUMBER, P_SONG_ID_097 NUMBER, P_SONG_ID_098 NUMBER, P_SONG_ID_099 NUMBER, P_SONG_ID_100 NUMBER
IS
select
from PRICE_DATA@PRICING_DB
where COUNTRY = 'USA'
and START_DATE <= sysdate
and END_DATE > sysdate
and vpc.SONG_ID IN
P_SONG_ID_001 ,P_SONG_ID_002 ,P_SONG_ID_003 ,P_SONG_ID_004 ,P_SONG_ID_005 ,P_SONG_ID_006 ,P_SONG_ID_007 ,P_SONG_ID_008 ,P_SONG_ID_009 ,P_SONG_ID_010,
P_SONG_ID_011 ,P_SONG_ID_012 ,P_SONG_ID_013 ,P_SONG_ID_014 ,P_SONG_ID_015 ,P_SONG_ID_016 ,P_SONG_ID_017 ,P_SONG_ID_018 ,P_SONG_ID_019 ,P_SONG_ID_020,
P_SONG_ID_021 ,P_SONG_ID_022 ,P_SONG_ID_023 ,P_SONG_ID_024 ,P_SONG_ID_025 ,P_SONG_ID_026 ,P_SONG_ID_027 ,P_SONG_ID_028 ,P_SONG_ID_029 ,P_SONG_ID_030,
P_SONG_ID_031 ,P_SONG_ID_032 ,P_SONG_ID_033 ,P_SONG_ID_034 ,P_SONG_ID_035 ,P_SONG_ID_036 ,P_SONG_ID_037 ,P_SONG_ID_038 ,P_SONG_ID_039 ,P_SONG_ID_040,
P_SONG_ID_041 ,P_SONG_ID_042 ,P_SONG_ID_043 ,P_SONG_ID_044 ,P_SONG_ID_045 ,P_SONG_ID_046 ,P_SONG_ID_047 ,P_SONG_ID_048 ,P_SONG_ID_049 ,P_SONG_ID_050,
P_SONG_ID_051 ,P_SONG_ID_052 ,P_SONG_ID_053 ,P_SONG_ID_054 ,P_SONG_ID_055 ,P_SONG_ID_056 ,P_SONG_ID_057 ,P_SONG_ID_058 ,P_SONG_ID_059 ,P_SONG_ID_060,
P_SONG_ID_061 ,P_SONG_ID_062 ,P_SONG_ID_063 ,P_SONG_ID_064 ,P_SONG_ID_065 ,P_SONG_ID_066 ,P_SONG_ID_067 ,P_SONG_ID_068 ,P_SONG_ID_069 ,P_SONG_ID_070,
P_SONG_ID_071 ,P_SONG_ID_072 ,P_SONG_ID_073 ,P_SONG_ID_074 ,P_SONG_ID_075 ,P_SONG_ID_076 ,P_SONG_ID_077 ,P_SONG_ID_078 ,P_SONG_ID_079 ,P_SONG_ID_080,
P_SONG_ID_081 ,P_SONG_ID_082 ,P_SONG_ID_083 ,P_SONG_ID_084 ,P_SONG_ID_085 ,P_SONG_ID_086 ,P_SONG_ID_087 ,P_SONG_ID_088 ,P_SONG_ID_089 ,P_SONG_ID_090,
P_SONG_ID_091 ,P_SONG_ID_092 ,P_SONG_ID_093 ,P_SONG_ID_094 ,P_SONG_ID_095 ,P_SONG_ID_096 ,P_SONG_ID_097 ,P_SONG_ID_098 ,P_SONG_ID_099 ,P_SONG_ID_100
group by
vpc.SONG_ID
,vpc.STOREFRONT_ID
TYPE SONG_ID_TYPE IS TABLE OF MUSIC@MUSIC_DB%TYPE INDEX BY BINARY_INTEGER;
V_SONG_ID_ARRAY SONG_ID_TYPE ;
v_commit_counter NUMBER := 0;
BEGIN
/* open cursor you intent to bulk collect from */
OPEN C_CURRENT_MUSIC;
LOOP
/* in batches of 100, bulk collect ADAM_ID mapped TMS_IDENTIFIER into PLSQL table or records */
FETCH C_CURRENT_MUSIC BULK COLLECT INTO V_SONG_ID_ARRAY LIMIT 100;
EXIT WHEN V_SONG_ID_ARRAY.COUNT = 0;
/* to avoid NO DATA FOUND error when pass 100 parameters to OPEN cursor, if the arrary
is not fully populated to 100, pad the array with nulls to fill up to 100 cells. */
IF (V_SONG_ID_ARRAY.COUNT >=1 and V_SONG_ID_ARRAY.COUNT <> 100) THEN
FOR j IN V_SONG_ID_ARRAY.COUNT+1..100 LOOP
V_SONG_ID_ARRAY(j) := null;
END LOOP;
END IF;
/* pass a batch of 100 to cursor that get price information per SONG_ID and STOREFRONT_ID */
FOR j IN C_get_music_price_data
V_SONG_ID_ARRAY(1) ,V_SONG_ID_ARRAY(2) ,V_SONG_ID_ARRAY(3) ,V_SONG_ID_ARRAY(4) ,V_SONG_ID_ARRAY(5) ,V_SONG_ID_ARRAY(6) ,V_SONG_ID_ARRAY(7) ,V_SONG_ID_ARRAY(8) ,V_SONG_ID_ARRAY(9) ,V_SONG_ID_ARRAY(10) ,
V_SONG_ID_ARRAY(11) ,V_SONG_ID_ARRAY(12) ,V_SONG_ID_ARRAY(13) ,V_SONG_ID_ARRAY(14) ,V_SONG_ID_ARRAY(15) ,V_SONG_ID_ARRAY(16) ,V_SONG_ID_ARRAY(17) ,V_SONG_ID_ARRAY(18) ,V_SONG_ID_ARRAY(19) ,V_SONG_ID_ARRAY(20) ,
V_SONG_ID_ARRAY(21) ,V_SONG_ID_ARRAY(22) ,V_SONG_ID_ARRAY(23) ,V_SONG_ID_ARRAY(24) ,V_SONG_ID_ARRAY(25) ,V_SONG_ID_ARRAY(26) ,V_SONG_ID_ARRAY(27) ,V_SONG_ID_ARRAY(28) ,V_SONG_ID_ARRAY(29) ,V_SONG_ID_ARRAY(30) ,
V_SONG_ID_ARRAY(31) ,V_SONG_ID_ARRAY(32) ,V_SONG_ID_ARRAY(33) ,V_SONG_ID_ARRAY(34) ,V_SONG_ID_ARRAY(35) ,V_SONG_ID_ARRAY(36) ,V_SONG_ID_ARRAY(37) ,V_SONG_ID_ARRAY(38) ,V_SONG_ID_ARRAY(39) ,V_SONG_ID_ARRAY(40) ,
V_SONG_ID_ARRAY(41) ,V_SONG_ID_ARRAY(42) ,V_SONG_ID_ARRAY(43) ,V_SONG_ID_ARRAY(44) ,V_SONG_ID_ARRAY(45) ,V_SONG_ID_ARRAY(46) ,V_SONG_ID_ARRAY(47) ,V_SONG_ID_ARRAY(48) ,V_SONG_ID_ARRAY(49) ,V_SONG_ID_ARRAY(50) ,
V_SONG_ID_ARRAY(51) ,V_SONG_ID_ARRAY(52) ,V_SONG_ID_ARRAY(53) ,V_SONG_ID_ARRAY(54) ,V_SONG_ID_ARRAY(55) ,V_SONG_ID_ARRAY(56) ,V_SONG_ID_ARRAY(57) ,V_SONG_ID_ARRAY(58) ,V_SONG_ID_ARRAY(59) ,V_SONG_ID_ARRAY(60) ,
V_SONG_ID_ARRAY(61) ,V_SONG_ID_ARRAY(62) ,V_SONG_ID_ARRAY(63) ,V_SONG_ID_ARRAY(64) ,V_SONG_ID_ARRAY(65) ,V_SONG_ID_ARRAY(66) ,V_SONG_ID_ARRAY(67) ,V_SONG_ID_ARRAY(68) ,V_SONG_ID_ARRAY(69) ,V_SONG_ID_ARRAY(70) ,
V_SONG_ID_ARRAY(71) ,V_SONG_ID_ARRAY(72) ,V_SONG_ID_ARRAY(73) ,V_SONG_ID_ARRAY(74) ,V_SONG_ID_ARRAY(75) ,V_SONG_ID_ARRAY(76) ,V_SONG_ID_ARRAY(77) ,V_SONG_ID_ARRAY(78) ,V_SONG_ID_ARRAY(79) ,V_SONG_ID_ARRAY(80) ,
V_SONG_ID_ARRAY(81) ,V_SONG_ID_ARRAY(82) ,V_SONG_ID_ARRAY(83) ,V_SONG_ID_ARRAY(84) ,V_SONG_ID_ARRAY(85) ,V_SONG_ID_ARRAY(86) ,V_SONG_ID_ARRAY(87) ,V_SONG_ID_ARRAY(88) ,V_SONG_ID_ARRAY(89) ,V_SONG_ID_ARRAY(90) ,
V_SONG_ID_ARRAY(91) ,V_SONG_ID_ARRAY(92) ,V_SONG_ID_ARRAY(93) ,V_SONG_ID_ARRAY(94) ,V_SONG_ID_ARRAY(95) ,V_SONG_ID_ARRAY(96) ,V_SONG_ID_ARRAY(97) ,V_SONG_ID_ARRAY(98) ,V_SONG_ID_ARRAY(99) ,V_SONG_ID_ARRAY(100)
LOOP
/* do stuff with data from Song and Pricing Database coming from the two
separate cursors, then continue processing more rows...
END LOOP;
/* commit after each batch of 100 SONG_IDs is processed */
COMMIT;
EXIT WHEN C_CURRENT_MUSIC%NOTFOUND; -- exit when there are no more rows to fetch from cursor
END LOOP; -- bulk fetching loop
CLOSE C_CURRENT_MUSIC; -- close cursor that was used in bulk collection
/* commit rows */
COMMIT; -- commit any remaining uncommitted data.
END;I've got a problem when using passing VARRAY of numbers as parameter to remote cursor: it takes a super long time to run, sometimes doesn't finish even after an hour as passed.
Continuing with my example in original entry, I replaced the bulk collect into PLSQL table collection with a VARRAY and i bulk collect into the VARRAY, this is fast and I know it works because I can DBMS_OUTPUT.PUT_LINE cells of VARRAY so I know it is getting populated correctly. However, when I pass the VARRAY containing 100 cells populated with SONG_IDs as parameter to cursor, execution time is over an hour and when I am expecting a few seconds.
Below code example strips the problem down to it's raw details, I skip the bulk collect and just manually populate a VARRAY with 100 SONG_ID values, then try to pass to as parameter to a cursor, but the execution time of cursor is unexpectedly long, over 30 minutes, sometime longer, when I am expecting seconds.
IMPORTANT: If I take the same 100 SONG_IDs and place them directly in the cursor query's where IN clause, the SQL runs in under 5 seconds and returns result. Also, if I pass the 100 SONG_IDs as individual cells of a PLSQL table collection, then it also runs fast.
I thought that since the VARRAY is used via select subquery that is it queried locally, but the cursor is remote, and that I had a distribute problem on my hands, so I put in the DRIVING_SITE hint to attempt to force the result of query against VARRAY to go to remote server and rest of query will run there before returning result, but that didn't work either, still got slow response.
Is something wrong with my code, or I am running into a Oracle problem that may require support to resolve?
DECLARE
/* define a parameterized cursor that accepts XXX number of in SONG_IDs and
retrieves required pricing information
CURSOR C_get_music_price_data
p_array_song_ids SYS.ODCInumberList
IS
select /*+DRIVING_SITE(pd) */
count(distinct s.EVE_ID)
from PRICE_DATA@PRICING_DB pd
where pd.COUNTRY = 'USA'
and pd.START_DATE <= sysdate
and pd.END_DATE > sysdate
and pd.SONG_ID IN
select column_value from table(p_array_song_ids)
group by
pd.SONG_ID
,pd.STOREFRONT_ID
V_ARRAY_SONG_IDS SYS.ODCInumberList := SYS.ODCInumberList();
BEGIN
V_ARRAY_SONG_IDS.EXTEND(100);
V_ARRAY_SONG_IDS( 1 ) := 31135 ;
V_ARRAY_SONG_IDS( 2 ) := 31140 ;
V_ARRAY_SONG_IDS( 3 ) := 31142 ;
V_ARRAY_SONG_IDS( 4 ) := 31144 ;
V_ARRAY_SONG_IDS( 5 ) := 31146 ;
V_ARRAY_SONG_IDS( 6 ) := 31148 ;
V_ARRAY_SONG_IDS( 7 ) := 31150 ;
V_ARRAY_SONG_IDS( 8 ) := 31152 ;
V_ARRAY_SONG_IDS( 9 ) := 31154 ;
V_ARRAY_SONG_IDS( 10 ) := 31156 ;
V_ARRAY_SONG_IDS( 11 ) := 31158 ;
V_ARRAY_SONG_IDS( 12 ) := 31160 ;
V_ARRAY_SONG_IDS( 13 ) := 33598 ;
V_ARRAY_SONG_IDS( 14 ) := 33603 ;
V_ARRAY_SONG_IDS( 15 ) := 33605 ;
V_ARRAY_SONG_IDS( 16 ) := 33607 ;
V_ARRAY_SONG_IDS( 17 ) := 33609 ;
V_ARRAY_SONG_IDS( 18 ) := 33611 ;
V_ARRAY_SONG_IDS( 19 ) := 33613 ;
V_ARRAY_SONG_IDS( 20 ) := 33615 ;
V_ARRAY_SONG_IDS( 21 ) := 33617 ;
V_ARRAY_SONG_IDS( 22 ) := 33630 ;
V_ARRAY_SONG_IDS( 23 ) := 33632 ;
V_ARRAY_SONG_IDS( 24 ) := 33636 ;
V_ARRAY_SONG_IDS( 25 ) := 33638 ;
V_ARRAY_SONG_IDS( 26 ) := 33640 ;
V_ARRAY_SONG_IDS( 27 ) := 33642 ;
V_ARRAY_SONG_IDS( 28 ) := 33644 ;
V_ARRAY_SONG_IDS( 29 ) := 33646 ;
V_ARRAY_SONG_IDS( 30 ) := 33648 ;
V_ARRAY_SONG_IDS( 31 ) := 33662 ;
V_ARRAY_SONG_IDS( 32 ) := 33667 ;
V_ARRAY_SONG_IDS( 33 ) := 33669 ;
V_ARRAY_SONG_IDS( 34 ) := 33671 ;
V_ARRAY_SONG_IDS( 35 ) := 33673 ;
V_ARRAY_SONG_IDS( 36 ) := 33675 ;
V_ARRAY_SONG_IDS( 37 ) := 33677 ;
V_ARRAY_SONG_IDS( 38 ) := 33679 ;
V_ARRAY_SONG_IDS( 39 ) := 33681 ;
V_ARRAY_SONG_IDS( 40 ) := 33683 ;
V_ARRAY_SONG_IDS( 41 ) := 33685 ;
V_ARRAY_SONG_IDS( 42 ) := 33700 ;
V_ARRAY_SONG_IDS( 43 ) := 33702 ;
V_ARRAY_SONG_IDS( 44 ) := 33704 ;
V_ARRAY_SONG_IDS( 45 ) := 33706 ;
V_ARRAY_SONG_IDS( 46 ) := 33708 ;
V_ARRAY_SONG_IDS( 47 ) := 33710 ;
V_ARRAY_SONG_IDS( 48 ) := 33712 ;
V_ARRAY_SONG_IDS( 49 ) := 33723 ;
V_ARRAY_SONG_IDS( 50 ) := 33725 ;
V_ARRAY_SONG_IDS( 51 ) := 33727 ;
V_ARRAY_SONG_IDS( 52 ) := 33729 ;
V_ARRAY_SONG_IDS( 53 ) := 33731 ;
V_ARRAY_SONG_IDS( 54 ) := 33733 ;
V_ARRAY_SONG_IDS( 55 ) := 33735 ;
V_ARRAY_SONG_IDS( 56 ) := 33737 ;
V_ARRAY_SONG_IDS( 57 ) := 33749 ;
V_ARRAY_SONG_IDS( 58 ) := 33751 ;
V_ARRAY_SONG_IDS( 59 ) := 33753 ;
V_ARRAY_SONG_IDS( 60 ) := 33755 ;
V_ARRAY_SONG_IDS( 61 ) := 33757 ;
V_ARRAY_SONG_IDS( 62 ) := 33759 ;
V_ARRAY_SONG_IDS( 63 ) := 33761 ;
V_ARRAY_SONG_IDS( 64 ) := 33763 ;
V_ARRAY_SONG_IDS( 65 ) := 33775 ;
V_ARRAY_SONG_IDS( 66 ) := 33777 ;
V_ARRAY_SONG_IDS( 67 ) := 33779 ;
V_ARRAY_SONG_IDS( 68 ) := 33781 ;
V_ARRAY_SONG_IDS( 69 ) := 33783 ;
V_ARRAY_SONG_IDS( 70 ) := 33785 ;
V_ARRAY_SONG_IDS( 71 ) := 33787 ;
V_ARRAY_SONG_IDS( 72 ) := 33789 ;
V_ARRAY_SONG_IDS( 73 ) := 33791 ;
V_ARRAY_SONG_IDS( 74 ) := 33793 ;
V_ARRAY_SONG_IDS( 75 ) := 33807 ;
V_ARRAY_SONG_IDS( 76 ) := 33809 ;
V_ARRAY_SONG_IDS( 77 ) := 33811 ;
V_ARRAY_SONG_IDS( 78 ) := 33813 ;
V_ARRAY_SONG_IDS( 79 ) := 33815 ;
V_ARRAY_SONG_IDS( 80 ) := 33817 ;
V_ARRAY_SONG_IDS( 81 ) := 33819 ;
V_ARRAY_SONG_IDS( 82 ) := 33821 ;
V_ARRAY_SONG_IDS( 83 ) := 33823 ;
V_ARRAY_SONG_IDS( 84 ) := 33825 ;
V_ARRAY_SONG_IDS( 85 ) := 33839 ;
V_ARRAY_SONG_IDS( 86 ) := 33844 ;
V_ARRAY_SONG_IDS( 87 ) := 33846 ;
V_ARRAY_SONG_IDS( 88 ) := 33848 ;
V_ARRAY_SONG_IDS( 89 ) := 33850 ;
V_ARRAY_SONG_IDS( 90 ) := 33852 ;
V_ARRAY_SONG_IDS( 91 ) := 33854 ;
V_ARRAY_SONG_IDS( 92 ) := 33856 ;
V_ARRAY_SONG_IDS( 93 ) := 33858 ;
V_ARRAY_SONG_IDS( 94 ) := 33860 ;
V_ARRAY_SONG_IDS( 95 ) := 33874 ;
V_ARRAY_SONG_IDS( 96 ) := 33879 ;
V_ARRAY_SONG_IDS( 97 ) := 33881 ;
V_ARRAY_SONG_IDS( 98 ) := 33883 ;
V_ARRAY_SONG_IDS( 99 ) := 33885 ;
V_ARRAY_SONG_IDS(100 ) := 33889 ;
/* do stuff with data from Song and Pricing Database coming from the two
separate cursors, then continue processing more rows...
FOR i IN C_get_music_price_data( v_array_song_ids ) LOOP
. (this is the loop where I pass in v_array_song_ids
. populated with only 100 cells and it runs forever)
END LOOP;
END; -
Hello
Oracle 11gR2.
I have a table with around 60 Million records, the structure likes bellow. The ID is generated by the sequence with gaps.
There is a scheduled job to analysis each records. We would like to select 1000 each time in the LOOP. The ID must order by asc, and each ID only can be selected once.
I would like to have only ONE select statement to have all columns needed and the max ID processed. This max ID will be used for next loop:
select id, name, ..., maxID from del_test where ID > maxID and rownum <= 1000 order by ID;
SQL*Plus>select * from del_test;
ID NAME
1 abc
2 abc
3 abc
4 abc
5 abc
6 abc
7 abc
8 abc
9 abc
10 abc
101 abc
102 abc
103 abc
104 abc
105 abc
106 abc
107 abc
108 abc
109 abc
110 abc
211 abc
212 abc
213 abc
214 abc
215 abc
216 abc
217 abc
218 abc
219 abc
220 abc
Thanks in advance!You can use limit clause(bulk collect) in plsql.
-
How to fetch from cursor into plsql collection
Dear Friends,
I am trying to understand PLSQL collections. I am trying with the following example.
CREATE OR REPLACE TYPE emp_obj AS OBJECT
( empname VARCHAR2(100), empjob VARCHAR2(50), empsal NUMBER);
CREATE OR REPLACE TYPE emp_tbl IS TABLE OF emp_obj;
CREATE OR REPLACE PACKAGE eg_collection AS
-- Delcare ref cursor
TYPE rc IS REF CURSOR;
-- Procedure
PROCEDURE eg_collection_proc (out_result OUT rc);
END;
CREATE OR REPLACE PACKAGE BODY eg_collection AS
PROCEDURE eg_collection_proc( out_result OUT rc) AS
emp_tdt emp_tbl := emp_tbl(emp_obj('oracle','DBA',100));
CURSOR c2 IS SELECT ename,job,sal FROM emp WHERE sal > 2000;
-- Declare a record type to hold the records from cursor and then pass to the collection
emp_rec emp_obj;
BEGIN
OPEN c2;
LOOP FETCH c1 INTO emp_rec;
EXIT WHEN c1%NOTFOUND;
emp_tdt.extend;
emp_tdt(emp_tdt.count) := emp_rec;
END LOOP;
CLOSE c2;
OPEN out_result FOR SELECT * FROM TABLE(CAST(emp_tdt AS emp_tbl));
END eg_collection_proc;
END eg_collection;
Executing the proc
variable r refcursor;
exec eg_collection.eg_collection_proc(:r);
print r;
But I am getting compilation error type mismatch found at emp_rec between fetch cursor into variableI am trying to understand PLSQL collections. I dont why the code is not working
SQL> CREATE OR REPLACE TYPE emp_obj AS OBJECT
2 (
3 empname VARCHAR2(100),
4 empjob VARCHAR2(50),
5 empsal NUMBER
6 )
7 /
Type created.
SQL> CREATE OR REPLACE TYPE emp_tbl IS TABLE OF emp_obj
2 /
Type created.
SQL> DECLARE
2 emp_tdt emp_tbl := emp_tbl ();
3 BEGIN
4
5 emp_tdt.extend;
6 SELECT emp_obj(ename, job, sal) BULK COLLECT INTO emp_tdt
7 FROM emp WHERE sal < 4000;
8
9 DBMS_OUTPUT.PUT_LINE ('The total count is ' || emp_tdt.count);
10
11 emp_tdt.extend;
12 SELECT ename, job, sal INTO emp_tdt(1).empname, emp_tdt(1).empjob, emp_tdt(1).empsal
13 FROM emp WHERE empno = 7900;
14
15 DBMS_OUTPUT.PUT_LINE ('The total count is ' || emp_tdt.count);
16
17 END;
18 /
The total count is 13
The total count is 14
PL/SQL procedure successfully completed.
SQL> DECLARE
2 emp_tdt emp_tbl := emp_tbl ();
3 BEGIN
4
5 emp_tdt.extend;
6 SELECT ename, job, sal INTO emp_tdt(1).empname, emp_tdt(1).empjob, emp_tdt(1).empsal
7 FROM emp WHERE empno = 7900;
8
9 DBMS_OUTPUT.PUT_LINE ('The total count is ' || emp_tdt.count);
10
11 emp_tdt.extend;
12 SELECT emp_obj(ename, job, sal) BULK COLLECT INTO emp_tdt
13 FROM emp WHERE sal < 4000;
14
15 DBMS_OUTPUT.PUT_LINE ('The total count is ' || emp_tdt.count);
16 END;
17 /
DECLARE
ERROR at line 1:
ORA-06530: Reference to uninitialized composite
ORA-06512: at line 6 -
Select data from plsql collections
Hi All,
I am not a developer but working as a DBA, so not very much familiar with pl/sql, still gone through with documentation and could come up with some solution of my problem. I need some expert advice here.
Problem : I am writing down some kind of plsql program for monitoring of some special batch job, I know we have lot of other option to do the same including db/grid control ..etc but for some
reason i have to do this using plsql only.
Requirement : my requirement is to select data from table in plsql and then should have ability to query it again and again. I would not prefer to go to table rather than directly from plsql..
I wrote down below code for sample, bulk collect data into collection type and can print using for loop.
Declare
type ts is table of v$session%rowtype index by pls_integer;
tsess ts;
begin
select * bulk collect into tsess from v$session ;
for i in 1..tsess.count loop
dbms_output.put_line(tsess(i).terminal);
end loop;
end;
But, is there any way same collection ( tsess in above example ) can be queried using select statement like 'select * from table ( Tsess ) ' I have searched on net and found this can be done using creating type at database level. But my problem is I can not create any object in database as being it is a production one.
I was looking for if is there any way same can be accomplished ... like cast / multiset .. however, I could not get it through.
your help would be appreciated !!
Regards,I don't think you need to use arrays here, only SQL, have a look at subquery factors and report back if that is insufficient...
Edited by: BrendanP on 12-Feb-2012 03:07 to add an example:
I gather that you want to 'requery' data that you have already got from the database purely to be able to use SQL functionality such as ORDER BY in multiple ways. Here is how you can do this in the original SQL for one particular example, where you want to query v$sql ordering by CPU time and by disk reads separately (I tested this but the output won't look good here, so omitting it):
WITH v AS (
SELECT
Substr (sql_text,1,500) sql_text,
cpu_time/1000000 cpu_seconds,
disk_reads,
buffer_gets,
executions,
CASE WHEN rows_processed != 0 THEN Round( buffer_gets / Nvl (Replace (rows_processed, 0, 1) ,1)) END Buffer_gets_rows_proc,
Round (buffer_gets / Nvl (Replace (executions, 0, 1), 1)) Buffer_gets_executions,
elapsed_time / 1000000 elapsed_second,
module
FROM v$sql s)
SELECT
'CPU' order_by,
cpu_seconds order_val,
sql_text,
cpu_seconds,
disk_reads,
buffer_gets,
executions,
buffer_gets_rows_proc,
buffer_gets_executions,
elapsed_second,
module
FROM v
UNION
SELECT
'Disk reads',
disk_reads,
sql_text,
cpu_seconds,
disk_reads,
buffer_gets,
executions,
buffer_gets_rows_proc,
buffer_gets_executions,
elapsed_second,
module
FROM v
ORDER BY order_by, order_val DESC -
What are collections in oracle plsql, and Transpose concepts.
Hi OTN,
what are the collections available in Oracle Plsql, what are concepts of collection.
How to Transpose a Table from rows to columns or columns into rows.
DDL and DML concepts.
What is the concepts of statistics in Oracle Plsql.
Thanks
Edited by: 945059 on Aug 22, 2012 4:52 AM945059 wrote:
Hi OTN,
what are the collections available in Oracle Plsql, what are concepts of collection.
How to Transpose a Table from rows to columns or columns into rows.
DDL and DML concepts.
What is the concepts of statistics in Oracle Plsql.
Thanks
Edited by: 945059 on Aug 22, 2012 4:52 AMhttp://www.google.co.in/search?hl=en-IN&source=hp&q=collections+oracle&gbv=2&oq=collections+oracle&gs_l=heirloom-hp.3..0l4j0i30l6.2031.5874.0.6561.18.17.0.0.0.0.422.3217.2-4j4j2.10.0...0.0...1c.l6qRfaAtkWM&safe=active
SQL and PL/SQL FAQ
http://www.google.co.in/search?q=performance+tuning+oracle&hl=en-IN&gbv=2&gs_l=heirloom-hp.3..0l4j0i30l6.2031.5874.0.6561.18.17.0.0.0.0.422.3217.2-4j4j2.10.0...0.0...1c.l6qRfaAtkWM&safe=active&oq=performance+tuning+oracle -
Hi,
I am working with oracle 10g.
Still i was not familiar with PLSQL Tables or collections.
Please send me the link or any notes regarding PLSQL Tables.
Thanks and Regards,
Ansaf.Ansaf wrote:
Hi,
I am working with oracle 10g.
Still i was not familiar with PLSQL Tables or collections.
Please send me the link or any notes regarding PLSQL Tables.
Thanks and Regards,
Ansaf.when all else fail Read The Fine Manual
http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14261/collections.htm#sthref1031 -
Wat's Plsql collections?
Can anyone help me about Plsql collections and why we need this?
Welcome to the forum.
Your question is quite broad.
A quick search through the Oracle docs will give you explanations and examples
http://www.oracle.com/pls/db112/search?remark=quick_search&word=collections
http://www.oracle.com/pls/db112/homepage
As well as a search on AskTom, for example:
http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:3170352229012
As well as a search on this forum.
why we need this?It depends. Perhaps you don't need them, perhaps you do.
Amongst others on your specific requirement and your datamodel. -
PLSQL COLLECTIONS(10g)
Hi People,
I have a clarification in plsql collections.it is defined that plsql collections are used to collect values of same data type.but in 10g document it is told that you can also use INDEX BY tables along with %ROWTYPE.how this is possible?.%ROWTYPE is used to draw different data types.how to use this along with INDEX BY tables. Pls help me with some sample codes.
with regards
vidsvidusnat wrote:
In the above example plsql table is used with %ROWTYPE It is not a PL/SQL "+table+". There is no such thing. No such concept. It is INCORRECT terminology used by many, including Oracle. (Oracle has however corrected this terminology in recent documentation).
That type defines an associative array.
which is used to collect values of different data types.Correct. The +%RowType+ clause saves us time and effort in redefining a PL/SQL record structure that duplicates the structure (SQL projection) of a table, view or cursor.
So in effect, instead of having to code this, we use +%RowType+ instead.
declare
type TEmployeeRecord is record(
emp_id number,
surname varchar2(80),
.. etc ..
type EmpTabTyp is table of TEmployeeRecord
index by pls_integer;To manually define a structure like this each time for a table/view/cursor is lots of coding. Easy to get wrong. And if the underlying SQL projection changes, then we need to manually update the structure.
So +%RowType+ saves us all the extra coding and maintenance of defining a PL/SQL struct that duplicates a SQL projection structure. If you know C/C++, think of it as a compiler macro that defines the relevant struct for you.
but plsql collections are defined to collect values of same data type.You have not define a collection. A collection is a different type of structure and has different features. You have defined an associative array.
using %ROWTYPE is contrary to plsql collection's definition.can anyone pls explain me how it is possible?There is no contradiction here. Just confusion it seems?
A collection is not an associative array. An associative array is not a collection. Both can be based on the same structure. Both can be used to received SQL cursor output. However, there are differences in features - especially how one addresses the contents. In essence, an associative array is addressed via name. Each cell in the array is named - or in the case of the name being a numeric, a number value. The 1st cell in the associative array can be named (or numbered in your case) using "100" - as you did in your sample code. So to address the contents of the 1st cell in that array, you need to reference it by index value 100. Not 1.
A collection is not addressed via a name of the cell. Instead, it is addressed by location/position of the cell. So the 1st cell will be addressed by 1, the 2nd cell by 2 and so on. -
Database table has two columns category and products.
Table: catalog
category products
fruit apple
vegetable carrot
soda pepsi
vegetable potato
fruit grapes
fruit orange
vegetable cabbage
soda coke
i need to read the records from table catalog and store them in some sort of plsql collection. I then have to read from that collection and write output as follows:
Note: the categories and products should be sorted alphabetically in output.
OUTPUT
fruit apple, grapes, orange
soda coke, pepsi
vegetable cabbage, carrot, potato
please help me as how this can be done?
Thanks
GWithout collections:
SQL> DECLARE
2 CURSOR c
3 IS
4 WITH t AS (
5 SELECT 'fruit' category,'apple' product FROM dual UNION ALL
6 SELECT 'vegetable','carrot' FROM dual UNION ALL
7 SELECT 'soda','pepsi' FROM dual UNION ALL
8 SELECT 'vegetable','potato' FROM dual UNION ALL
9 SELECT 'fruit','grapes' FROM dual UNION ALL
10 SELECT 'fruit','orange' FROM dual UNION ALL
11 SELECT 'vegetable','cabbage' FROM dual UNION ALL
12 SELECT 'soda','coke' FROM dual
13 )
14 SELECT category,
15 ltrim(sys_connect_by_path(product,', '),', ') product_list
16 FROM (
17 SELECT category,
18 product,
19 row_number() over(partition by category order by product) rn
20 FROM t
21 )
22 WHERE connect_by_isleaf = 1
23 START WITH rn = 1
24 CONNECT BY category = PRIOR category
25 AND rn = PRIOR rn + 1
26 ORDER BY category;
27 BEGIN
28 FOR v_rec IN c LOOP
29 DBMS_OUTPUT.PUT_LINE(rpad(v_rec.category,10) || v_rec.product_list);
30 END LOOP;
31 END;
32 /
fruit apple, grapes, orange
soda coke, pepsi
vegetable cabbage, carrot, potato
PL/SQL procedure successfully completed.
SQL> And in plain SQL:
SQL> COLUMN PRODUCT_LIST FORMAT A50
SQL> WITH t AS (
2 SELECT 'fruit' category,'apple' product FROM dual UNION ALL
3 SELECT 'vegetable','carrot' FROM dual UNION ALL
4 SELECT 'soda','pepsi' FROM dual UNION ALL
5 SELECT 'vegetable','potato' FROM dual UNION ALL
6 SELECT 'fruit','grapes' FROM dual UNION ALL
7 SELECT 'fruit','orange' FROM dual UNION ALL
8 SELECT 'vegetable','cabbage' FROM dual UNION ALL
9 SELECT 'soda','coke' FROM dual
10 )
11 SELECT category,
12 ltrim(sys_connect_by_path(product,', '),', ') product_list
13 FROM (
14 SELECT category,
15 product,
16 row_number() over(partition by category order by product) rn
17 FROM t
18 )
19 WHERE connect_by_isleaf = 1
20 START WITH rn = 1
21 CONNECT BY category = PRIOR category
22 AND rn = PRIOR rn + 1
23 ORDER BY category
24 /
CATEGORY PRODUCT_LIST
fruit apple, grapes, orange
soda coke, pepsi
vegetable cabbage, carrot, potato
SQL> SY. -
Dear forum,
What is the criteria to use bulk collect in our plsql programs
what are the oracle parameters relavent to bulk collect perfimance.
ThanksUse bulk collect anywhere that you can not use a simple SQL statement and, most often, within the context of a loop where in the old days a cursor loop would have been used.
Any parameter that affects memory or the optimizer can potentially affect bulk collect.
Homework research should be done at http://tahiti.oracle.com
Demos of this functionality can be found at http://www.psoug.org/library.html -
PLSQL Error while using collections dATABASE:10G
Hi,
I am getting below error while compiling below code:
Error: DML statement without BULK In-BIND cannot be used inside FORALL
Could you suggest.
create or replace PROCEDURE V_ACCT_MTH ( P_COMMIT_INTERVAL NUMBER DEFAULT 10000)
is
CURSOR CUR_D_CR_ACCT_MTH
IS
SELECT * FROM D_ACCT_MTH;
TYPE l_rec_type IS TABLE OF CUR_D_CR_ACCT_MTH%ROWTYPE
INDEX BY PLS_INTEGER;
v_var_tab l_rec_type;
v_empty_tab l_rec_type;
v_error_msg VARCHAR2(80);
v_err_code VARCHAR2(30);
V_ROW_CNT NUMBER :=0;
--R_DATA NUMBER :=1;
BEGIN
OPEN CUR_D_CR_ACCT_MTH;
v_var_tab := v_empty_tab;
LOOP
FETCH CUR_D_CR_ACCT_MTH BULK COLLECT INTO v_var_tab LIMIT P_COMMIT_INTERVAL;
EXIT WHEN v_var_tab.COUNT=0;
FORALL R_DATA IN 1..v_var_tab.COUNT
INSERT INTO ACCT_F_ACCT_MTH
DATE_KEY
,ACCT_KEY
,P_ID
,ORG_KEY
,FDIC_KEY
,BAL
,BAL1
,BAL2
,BAL3
,BAL4
,BAL5
,BAL6
,BAL7
,BAL8
,BAL9
,BAL10
,BAL11
,BAL12
,BAL13
,BAL14
,BAL15
VALUES
DATE_KEY(R_DATA)
,ACCT_KEY(R_DATA)
,P_ID(R_DATA)
,ORG_KEY(R_DATA)
,FDIC_KEY(R_DATA)
,BAL(R_DATA)
,BAL(R_DATA)
,BAL(R_DATA)
,BAL(R_DATA)
,BAL(R_DATA)
,BAL(R_DATA)
,BAL(R_DATA)
,BAL(R_DATA)
,BAL(R_DATA)
,BAL(R_DATA)
,BAL(R_DATA)
,BAL(R_DATA)
,BAL(R_DATA)
,BAL(R_DATA)
,BAL(R_DATA)
,BAL(R_DATA)
COMMIT;
END LOOP;
CLOSE CUR_D_CR_ACCT_MTH;
EXCEPTION
WHEN OTHERS THEN
v_error_msg:=substr(sqlerrm,1,50);
v_err_code :=sqlcode;
DBMS_OUTPUT.PUT_LINE(v_error_msg,v_err_code);
END V_ACCT_MTH;931832 wrote:
Here i am using above method using forall because of large volume of data.Which is a FLAWED approach. Always.
FORALL is not suited to "move/copy" large amounts of data from one table to another.
Any suggestion ?Use only SQL. It is faster. It has less overheads. It can execute in parallel.
So execute it in parallel to move/copy that data. You can roll this manually via the DBMS_PARALLEL_EXECUTE interface. Simplistic example:
declare
taskName varchar2(30) default 'PQ-task-1';
parallelSql varchar2(1000);
begin
--// create trask
DBMS_PARALLEL_EXECUTE.create_task( taskName );
--// chunk the table by rowid ranges
DBMS_PARALLEL_EXECUTE.create_chunks_by_rowid(
task_name => taskName,
table_owner => user,
table_name => 'D_ACCT_MNTH',
by_row => true,
chunk_size => 100000
--// create insert..select statement to copy a chunk of rows
parallelSql := 'insert into acct_f_acct_mth select * from d_acct_mnth
where rowid between :start_id and :end_id';
--// run the task using 5 parallel processes
DBMS_PARALLEL_EXECUTE.Run_Task(
task_name => taskName,
sql_stmt => parallelSql,
language_flag => DBMS_SQL.NATIVE,
parallel_level => 5
--// wait for it to complete
while DBMS_PARALLEL_EXECUTE.task_status( taskName ) != DBMS_PARALLEL_EXECUTE.Finished loop
DBMS_LOCK.Sleep(10);
end loop;
--// remove task
DBMS_PARALLEL_EXECUTE.drop_task( taskName );
end;
/Details in Oracle® Database PL/SQL Packages and Types Reference guide.
For 10g, the EXACT SAME approach can be used - by determining the rowid chunks/ranges via a SQL and then manually running parallel processes as DBMS_JOB. See {message:id=1108593} for details.
Maybe you are looking for
-
FTP to ABAP Proxy Scenario - getting error CO_TXT_CHANNEL_PASSWORD_ERROR
We have transported PI and EP data from development server to respective production, every thing is running fine except the abap proxy scenarios i.e. PI reads file from ftp location and calls the abap proxy but we are getting following errors: <?xml
-
I-Series chipsets netbooting across subnets
Hello all, Is anyone having issues attaching to tftp served netinstall images across subnet's with i-series hardware? Here's the situation, the netinstall.dmg was created form a factory build core i7 macbook pro mid 2012. Imaging on the same subnet a
-
Typing not showing up in password fields
<blockquote>Locking duplicate thread.<br> Please continue here: [/questions/837290]</blockquote> Hi folks, I have a strange one - I can type in a password into a password field in FF3.6.17, but the field stays blank (or sometimes a space shows up). T
-
Store a uploaded file of type binary into a java.sql.Blob
Hi all, I try a File-Upload and store the file in a java.sql.Blob of a MaxDB. My Problem is, that I'm not able to import a Model-Attribute of data type byte[]. Further I don't no how to convert the uploaded value attribute of data type binary, in a
-
Report Footer overlapping Last four records in the report body.
<p>Hi All,</p><p>In all of my reports have more than 20 Pages. All of my reports are Webintellegence format. these reports we deployed in Java Appplication. Java Application is in Tiles Frame Work Architecture. </p><p><strong>Here Problem is all of m