FORALL stmt
Hi there,
I 'm studying FORALL statement and I ran into a problem I don't understand.
I have a table:
create table employee_1 as select employee_id, last_name,first_name
from employees
where 1=2;
And I want to move the data from HR employees to it using FORALL.
How can I redo this, so I don't have to use dynamic SQL?
declare
type ln_type is table of varchar2(30)
index by pls_integer;
type id_type is table of number
index by pls_integer;
ln ln_type;
fn ln_type;
eid id_type;
v_counter integer:=0;
begin
for r in (select employee_id,last_name, first_name
from employees where employee_id >200)
loop
v_counter:=v_counter+1;
ln(v_counter):=r.last_name;
fn(v_counter):=r.first_name;
eid(v_counter):=r.employee_id;
end loop;
forall i in eid.first..eid.last
execute immediate
'insert into employees_1(employee_id,last_name,first_name)
values (:1,:2,:3)'
using eid(i),ln(i),fn(i);
end;
This works, but I want to write it with regular SQL (if that is possible?)
I tried it like this:
forall i in eid.first..eid.last
insert into employees_1(employee_id,last_name,first_name)
values (eid(i),ln(i),fn(i));
end;
but I keep getting
PLS-00430: FORALL iteration variable I is not allowed in this context
I googled the error and I got
Cause: FORALL iteration variable can only be used as a
subscript. It cannot be used directly or as a part of an
expression.
Action: Use FORALL variable only as a collection subscript.
Can somebody explain this to me in a more understandable manner?
And fix my code for if possible!
All help appreciated
Jana Kralova wrote:
By the way, you wouldn't by any chance know why I am not able to use
individual column table types. This is a good one. There is nothing wrong with using individual column table types, just using built-in function name as variable name can sometimes fool you quite a bit:
SQL> declare
2 type ln_type is table of varchar2(30)
3 index by pls_integer;
4 type id_type is table of number
5 index by pls_integer;
6 ln ln_type;
7 fn ln_type;
8 eid id_type;
9 v_counter integer:=0;
10 begin
11 select employee_id,
12 last_name,
13 first_name
14 bulk collect
15 into eid,
16 ln,
17 fn
18 from hr.employees
19 where employee_id >200;
20 v_counter:=v_counter+1;
21 forall i in eid.first..eid.last
22 insert into employees_1(employee_id,last_name,first_name)
23 values (eid(i),ln(i),fn(i));
24 end;
25 /
values (eid(i),ln(i),fn(i));
ERROR at line 23:
ORA-06550: line 23, column 27:
PLS-00430: FORALL iteration variable I is not allowed in this context
SQL> declare
2 type ln_type is table of varchar2(30)
3 index by pls_integer;
4 type id_type is table of number
5 index by pls_integer;
6 lnm ln_type;
7 fn ln_type;
8 eid id_type;
9 v_counter integer:=0;
10 begin
11 select employee_id,
12 last_name,
13 first_name
14 bulk collect
15 into eid,
16 lnm,
17 fn
18 from hr.employees
19 where employee_id >200;
20 v_counter:=v_counter+1;
21 forall i in eid.first..eid.last
22 insert into employees_1(employee_id,last_name,first_name)
23 values (eid(i),lnm(i),fn(i));
24 end;
25 /
PL/SQL procedure successfully completed.
SQL> Your problem is LN(I) is interpreted as built-in natural logarithm function LN with I as function parameter.
SY.
Similar Messages
-
Guys,
SQL> select * from v$version;
BANNER
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bi
PL/SQL Release 10.2.0.4.0 - Production
CORE 10.2.0.4.0 Production
TNS for Solaris: Version 10.2.0.4.0 - Production
NLSRTL Version 10.2.0.4.0 - Production
Problem: I wrote a procedure to parse a varchar2 field of a table.
It contains long strings. These strings are put into that column
by a java application. The procedure has an inline view which retrieve
records containing certain string pattern. The table has about
2 million records. After procedure gets the strings from the
inline view; for a particular pattern I found that inline view should
be containing 600k records; the Oracle regex function parses to put
the relevant parts into separate columns. At first, I thought, may be
inline view is the culprit. So, I created a staging table and ran my
procedure on it; I created a BTree index on the column. But, no results.
Then I thought DISTINCT keyword is the problem. Removed it, but still procedure
doesn't populate the tables. I am not sure what is going on. Even DBAs are
not sure. I told them to create an index on varchar2 column of original table. They have
created it but no improvement. Would someone please advice? I am new to sql tuning.
Is there any tutorial which explains with examples about sql tuning - I mean,
I am looking for something like
1. explain plan - What every field means?
2. dbms_prof - How to readthe output?
3. trace - how to use it? etc.
Thanks in advance!
CREATE OR REPLACE PROCEDURE prc_parse
IS
-- Purpose: Procedure to parse column of table
to retrieve crit, points,
comment, morecomment and
overallcomment.
-- MODIFICATION HISTORY
-- Person Date Comments
TYPE src_crit IS TABLE OF subtable.column1%TYPE;
TYPE src_points IS TABLE OF subtable.column1%TYPE;
TYPE src_comment IS TABLE OF subtable.column1%TYPE;
TYPE src_morecomment IS TABLE OF subtable.column1%TYPE;
TYPE src_overall_comment IS TABLE OF subtable.column1%TYPE;
src_crit_array src_crit;
src_points_array src_points;
src_comment_array src_comment;
src_morecomment_array src_morecomment;
src_overall_comment_array src_overall_comment;
CURSOR cur_latest
IS
SELECT DISTINCT
TRIM(REPLACE(REPLACE(SUBSTR(REGEXP_SUBSTR(string,'Crit:</strong>[^<]+', 1, level), 15),CHR(13),''),CHR(10),'')) crit,
TRIM(REPLACE(REPLACE(SUBSTR(REGEXP_SUBSTR(string,'points [^\)]+', 1, level), 8),CHR(13),''),CHR(10),'')) points,
TRIM(REPLACE(REPLACE(SUBSTR(REGEXP_SUBSTR(string,'\):[^<]+', 1, level), 3),CHR(13),''),CHR(10),'')) comment,
TRIM(REPLACE(REPLACE(SUBSTR(REGEXP_SUBSTR(string,'blockquote>[^<]+', 1, level), 12),CHR(13),''),CHR(10),'')) morecomment,
TRIM(REPLACE(REPLACE(SUBSTR(string, INSTR(string, '>', -1) + 1),CHR(13),''),CHR(10),'')) overallcomment
FROM (SELECT column1 string
FROM subtable
WHERE column1 LIKE '<strong>Crit:</strong>%'
CONNECT BY LEVEL <= (LENGTH(string) - LENGTH(REPLACE(string, 'Crit:')))/5;
BEGIN
OPEN cur_latest;
LOOP
FETCH cur_latest
BULK COLLECT INTO src_crit_array,
src_points_array,
src_comment_array,
src_morecomment_array,
src_overall_comment_array
LIMIT 100;
FORALL i in 1 .. src_crit_array.COUNT
INSERT INTO test_parse_table1 (
crit,
points,
comment,
morecomment
VALUES (
src_crit_array(i),
src_points_array(i),
src_comment_array(i),
src_morecomment_array(i)
FORALL i in 1 .. src_crit_array.COUNT
INSERT INTO test_parse_table2 (
overallcomment
VALUES (
src_overallcomment_array(i)
EXIT WHEN cur_latest%NOTFOUND;
COMMIT;
END LOOP;
COMMIT;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
DBMS_OUTPUT.PUT_LINE('Error:'||sqlerrm);
COMMIT;
END;
/Edited by: abyss on Sep 19, 2010 6:03 PM
Edited by: abyss on Oct 1, 2010 9:27 AMAbyss,
You can do multiple inserts using the FORALL stmt, I dont see any thing wrong with that code bit.
I tried it with the below eg & it worked fine for me ...
create table TBL_TEST
col1 NUMBER,
col2 NUMBER,
col3 CHAR(1)
create table tbl_test2
as
select t.col1, t.col2 from tbl_test t where 1=2;
create table tbl_test3
as
select t.* from tbl_test t where 1=2;
declare
type lt_prod_row is table of tbl_test.col1%type;
type lt_sup_row is table of tbl_test.col2%type;
type lt_pri_row is table of tbl_test.col3%type;
ltc1r lt_col1_row;
ltc2r lt_col2_row;
ltc3r lt_col3_row;
begin
select tbl.col1, tbl.col2, tbl.col3
bulk collect into ltc1r, ltc2r, ltc3r
from tbl_test tbl;
dbms_output.put_line(ltc1r.count);
forall i in 1..ltc1r.count
insert into tbl_test3 values (ltc1r(i), ltc2r(i), ltc3r(i));
forall i in 1..ltc1r.count
insert into tbl_test2 (col1, col2) values (ltc1r(i), ltc2r(i));
end;Which line of your code are you getting the error ? -
GETTING ERROR INVALID IDETIFIER
NEED HELP ASAP!!!!!!
ERROR MARKED AGAINT THE LINE...SEE THE LAST FEW LINWS FRM FORALL STMT
declare
type summary_upd_tab is table of summary%rowtype;
summary_upd_var summary_upd_tab;
begin
select
user_id,
min(start_time_utc),
max(end_time_utc),
sum(duration_seconds),
sum(upload_bytes),
sum(download_bytes),
sum(upload_bytes)+sum(download_bytes),
null,
null,
null,
type_of_summary,
ispeak,
null
--TOTALDISCOUNT
bulk collect into summary_upd_var
from aaa_sessions a
-- hsin_plan_details hpd
group by user_id,ispeak,type_of_summary;
forall i in summary_upd_var.first..summary_upd_var.last
update summary s
set
start_date=DECODE((summary_upd_var.start_date-s.start_date)-abs(summary_upd_var.start_date-s.start_date),0,s.start_date,summary_upd_var.start_date),
end_date=decode((summary_upd_var.end_time_utc-s.end_date)-abs(summary_upd_var.end_time_utc-s.end_date),0,summary_upd_var.end_time_utc,s.end_date),
total_duration=s.TOTAL_DURATION+summary_upd_var.total_duration,
total_upload=s.total_upload+summary_upd_var.total_upload,
total_download=s.total_download+summary_upd_var.total_download
--total_traffic=s.total_upload+summary_upd_var.total_upload+s.total_download+summary_upd_var.total_download
where
summary.user_id=summary_upd_var.user_id
and
summary.ispeak=summary_upd_var.ispeak
and
summary.TYPE_OF_SUMMARY=summary_upd_var.TYPE_OF_SUMMARY; -------INVALID IDENTIFIER????this column is present in the tablle...then why??
end;user8731258 wrote:
this is how my query looks like...
bu t i am nt very clear as to how correlated update would work?Here is a simple example of the workings:
SQL> create table t
2 as
3 select rownum id
4 , rownum + 2 tid
5 from all_objects
6 where rownum <= 5
7 /
Table created.
SQL> create table s
2 as
3 select *
4 from t
5 /
Table created.
SQL>
SQL> update s
2 set tid = tid * 2
3 /
5 rows updated.
SQL>
SQL> select *
2 from t
3 /
ID TID
1 3
2 4
3 5
4 6
5 7
SQL> select *
2 from s
3 /
ID TID
1 6
2 8
3 10
4 12
5 14
SQL>
SQL>
SQL> update t
2 set (id, tid) = (select s.id, s.tid
3 from s
4 where s.id = t.id)
5 ;
5 rows updated.
SQL> select *
2 from t
3 /
ID TID
1 6
2 8
3 10
4 12
5 14As you can see it works as advertised....
user8731258 wrote:
I still want to use collection..so plz tell me a workaround for this reference error!!!!Why?... the UPDATE works fine, anyway ...follow the links I posted before -
Binds collections and forall statement
version 9.2.0.6
I would like to make this more dynamic in that the collection cList can be used only once and be used by all bind variables. The variable stmt would be dynamically generated in that case it would insert into any number of tables.
Can this be done?
Is this feature available in a newer version of Oracle?
create table d2 nologging as
select
rownum rn
,substr(dbms_random.string('x',5),1,10) v1
,sysdate d1
,round(dbms_random.value(1,10)) n1
,substr(dbms_random.string('x',5),1,10) v2
,rpad(' ',4000,' ') as concat
from dual connect by level <= 100;
-- no rows for our test
create table d3 nologging as
select
from d2 where 1 = 2;
-- setup for our test
update d2
set image = rpad(nvl(to_char(rn),' '),10,' ')
|| rpad(nvl(v1,' '),20,' ')
|| rpad(nvl(to_char(d1,'DD-MON-YYYY HH24:MI:SS'),' '),34,' ')
|| rpad(nvl(to_char(n1),' '),10,' ')
|| rpad(nvl(v2,' '),10,' ')
-- test got all locations right
select
to_number(rtrim(substr(image,1,10)))
,rtrim(substr(image,11,20))
,to_date(rtrim(substr(image,30,34)),'DD-MON-YYYY HH24:MI:SS')
,to_number(rtrim(substr(image,65,10))) AS n1
,rtrim(substr(image,75,10))
from d2;
-- here is where we do the work
declare
type charList is table of varchar2(4000);
cList charList;
d2l d2_list;
errors NUMBER;
dml_errors EXCEPTION;
PRAGMA exception_init(dml_errors, -24381);
sqlStmt varchar2(32000);
cursor cur is select image from d2;
bcLimit number := 23;
begin
sqlStmt := 'insert into d3 (rn,v1,d1,n1,v2)'
|| 'values (to_number(rtrim(substr(:a,1,10)))
,rtrim(substr(:a,11,20))
,to_date(rtrim(substr(:a,30,34)),''DD-MON-YYYY HH24:MI:SS'')
,to_number(rtrim(substr(:a,65,10)))
,rtrim(substr(:a,75,10)))';
open cur;
loop
fetch cur bulk collect into cList limit bcLimit;
exit when cList.count = 0;
begin
-- very very unfortunately the code is unable to have one using clause variable be applied to all bind variables
-- note the number of cList uses having the bind variables all name the same does not help
-- using only one gets a ORA-1008 error :(
FORALL i IN cList.FIRST..cList.LAST SAVE EXCEPTIONS execute immediate sqlstmt using cList(i),cList(i),cList(i),cList(i),cList(i);
-- FORALL i IN cList.FIRST..cList.LAST SAVE EXCEPTIONS execute immediate sqlstmt using cList(i); --< DOES NOT WORK :( I WISH IT WOULD!
EXCEPTION
WHEN dml_errors THEN
errors := SQL%BULK_EXCEPTIONS.COUNT;
dbms_output.put_line('number of errors is ' || errors);
FOR i IN 1..errors LOOP
dbms_output.put_line('Error ' || i || ' occurred during iteration ' || SQL%BULK_EXCEPTIONS(i).ERROR_INDEX);
dbms_output.put_line('Could not insert ' || cList(SQL%BULK_EXCEPTIONS(i).ERROR_INDEX));
dbms_output.put_line(SQLERRM(-SQL%BULK_EXCEPTIONS(i).ERROR_CODE));
END LOOP;
end;
end loop;
close cur;
dbms_output.put_line('h2');
end;
/The CREATE TABLE you post for table D2 has no column called 'image'. It would help somewhat if you posted a working example.
Also I am not clear why the INSERT INTO D3 statement in the anonymous block needs to be dynamic. -
Hi,
I have written this procedure and I am getting
LINE/COL ERROR
69/5 PL/SQL: SQL Statement ignored
83/11 PL/SQL: ORA-00947: not enough values
CREATE OR REPLACE PROCEDURE f_t_s (P_F IN VARCHAR2)
IS
TYPE quote_cols_rt IS RECORD
twitter_gid twitter.twitter_gid%TYPE,
twitter_xid twitter.twitter_xid%TYPE,
origin_location_type twitter.origin_location_type%TYPE,
destination_location_type twitter.destination_location_type%TYPE,
is_hazardous twitter.is_hazardous%TYPE,
perspective twitter.perspective%TYPE,
twitter_option twitter.twitter_option%TYPE,
servprov_gid twitter.servprov_gid%TYPE,
origin_search_value twitter.origin_search_value%TYPE,
destination_search_value twitter.destination_search_value%TYPE,
domain_name twitter.domain_name%TYPE,
is_customer_rates_only twitter.is_customer_rates_only%TYPE
TYPE twitter_cols_tt IS TABLE OF twitter_cols_rt INDEX BY PLS_INTEGER;
twitter_cols_t twitter_cols_tt;
BEGIN
SELECT all_spec twitter_gid,
SUBSTR(all_spec,7) twitter_xid,
'location_code' origin_location_type,
'location_code' destination_location_type,
'N' is_hazardous,
'B' perspective,
'O' twitter_option,
'INDIA.'||servprov_xid servprov_gid,
SUBSTR(tm,1,2) ||':'||SUBSTR(tm,3) origin_search_value,
Location_xid destination_search_value,
'INDIA' domain_name,
'N' is_customer_rates_only
BULK COLLECT INTO twitter_cols_t
FROM
(SELECT x.*,
Q.twitter_gid
FROM
(SELECT 'INDIA.FS_'||H.servprov_xid||'_'||D.Location_xid||'_'||T.tm all_spec,
servprov_xid ,
tm ,
Location_xid
FROM
(SELECT Location_xid
FROM location
WHERE location_xid IN ('1')
AND domain_name ='INDIA'
) D,
(SELECT servprov_xid
FROM servprov
WHERE(servprov_gid LIKE 'P_F%'
AND SUBSTR(servprov_xid,2,1) IN ('2'))
OR servprov_gid ='INDIA.FRESHMISC'
) H,
(SELECT lpad(rownum-1,2,'0') ||'00' tm FROM sea WHERE rownum<25
UNION
SELECT lpad(rownum-1,2,'0') ||'30' tm FROM sea WHERE rownum<25
) T
) x,
(SELECT * FROM twitter WHERE twitter_gid LIKE 'INDIA.FS%'
) Q
WHERE x.all_spec=Q.twitter_gid(+)
WHERE twitter_gid IS NULL;
FORALL i in 1 .. twitter_cols_t.count
--LOOP
INSERT
INTO twitter
(twitter_gid ,
twitter_xid ,
origin_location_type ,
destination_location_type,
is_hazardous ,
perspective ,
twitter_option ,
servprov_gid ,
origin_search_value ,
destination_search_value ,
domain_name ,
is_customer_rates_only)
VALUES
twitter_cols_t (i);
--END LOOP;
END f_t_s;
Any idea where I am doing mistake
Thanks in Advance,
DIDIHi,
That was my typing mistake....
This is correct code
CREATE OR REPLACE PROCEDURE f_t_s (P_F IN VARCHAR2)
IS
TYPE twitter_cols_rt IS RECORD
twitter_gid twitter.twitter_gid%TYPE,
twitter_xid twitter.twitter_xid%TYPE,
origin_location_type twitter.origin_location_type%TYPE,
destination_location_type twitter.destination_location_type%TYPE,
is_hazardous twitter.is_hazardous%TYPE,
perspective twitter.perspective%TYPE,
twitter_option twitter.twitter_option%TYPE,
servprov_gid twitter.servprov_gid%TYPE,
origin_search_value twitter.origin_search_value%TYPE,
destination_search_value twitter.destination_search_value%TYPE,
domain_name twitter.domain_name%TYPE,
is_customer_rates_only twitter.is_customer_rates_only%TYPE
TYPE twitter_cols_tt IS TABLE OF twitter_cols_rt INDEX BY PLS_INTEGER;
twitter_cols_t twitter_cols_tt;
BEGIN
SELECT all_spec twitter_gid,
SUBSTR(all_spec,7) twitter_xid,
'location_code' origin_location_type,
'location_code' destination_location_type,
'N' is_hazardous,
'B' perspective,
'O' twitter_option,
'INDIA.'||servprov_xid servprov_gid,
SUBSTR(tm,1,2) ||':'||SUBSTR(tm,3) origin_search_value,
Location_xid destination_search_value,
'INDIA' domain_name,
'N' is_customer_rates_only
BULK COLLECT INTO twitter_cols_t
FROM
(SELECT x.*,
Q.twitter_gid
FROM
(SELECT 'INDIA.FS_'||H.servprov_xid||'_'||D.Location_xid||'_'||T.tm all_spec,
servprov_xid ,
tm ,
Location_xid
FROM
(SELECT Location_xid
FROM location
WHERE location_xid IN ('1')
AND domain_name ='INDIA'
) D,
(SELECT servprov_xid
FROM servprov
WHERE(servprov_gid LIKE 'P_F%'
AND SUBSTR(servprov_xid,2,1) IN ('2'))
OR servprov_gid ='INDIA.FRESHMISC'
) H,
(SELECT lpad(rownum-1,2,'0') ||'00' tm FROM sea WHERE rownum<25
UNION
SELECT lpad(rownum-1,2,'0') ||'30' tm FROM sea WHERE rownum<25
) T
) x,
(SELECT * FROM twitter WHERE twitter_gid LIKE 'INDIA.FS%'
) Q
WHERE x.all_spec=Q.twitter_gid(+)
WHERE twitter_gid IS NULL;
FORALL i in 1 .. twitter_cols_t.count
--LOOP
INSERT
INTO twitter
(twitter_gid ,
twitter_xid ,
origin_location_type ,
destination_location_type,
is_hazardous ,
perspective ,
twitter_option ,
servprov_gid ,
origin_search_value ,
destination_search_value ,
domain_name ,
is_customer_rates_only)
VALUES
twitter_cols_t (i);
--END LOOP;
END f_t_s;
Thanks,
DIDI -
Deletion is taking long time using forall
Hi,
i am inserting and deleting the rows using forall. insert taking less time to inset the rows but while coming to
deletion it is taking more than 5 days long time to delete 18.5 million rows in a table using forall.
the main table having 70 million rows.
the code is..
FETCH ref_typ BULK COLLECT INTO l_id_tbl LIMIT 10000;
begin
FORALL i in 1..l_id_tbl.COUNT
INSERT INTO change_test (id,
history,
transaction,
date)
VALUES (seq.nextval,
'CHANGE_HIS',
l_id_tbl(i),
sysdate);
exception
when others then
null;
end;
begin
FoRALL i in 1..l_id_tbl.COUNT
DELETE FROM change_his
where id = l_id_tbl(i);
exception
when others then
null;
end;
end loop;
so please give me a good solution to delete the rows less than 5 days..Why are you wanting to do this using BULK COLLECT and FORALL?
Why not just "insert ... select ..." and "delete ..."?
Loading records into expensive PGA memory to insert them back on the database is bound to be slower (and use more server resources) than just doing a straight insert ... select ... statement.
Explain exactly what you are trying to do.
Re: 2. How do I ask a question on the forums? -
JOB is created but SPOOL is not created - using SUBMIT stmt in WD
Hi,
I am submitting report from WD. PFB the code i used. This is cuccessfully creating the JOB in SM37 and the status is 'Finished'. But when I click for the SPOOL, it is giving me an error 'No list available'.
I used the following code for submitting the program.
* call the FM 'JOB_OPEN' and create the job.
SUBMIT ztest TO SAP-SPOOL
WITH pnppernr-low EQ pernr
WITH pnpbukrs-low EQ bukrs
SPOOL PARAMETERS lv_print_parameters
WITHOUT SPOOL DYNPRO
VIA JOB lv_name NUMBER lv_number " job name and number created from JOB_OPEN
AND RETURN.
* call the FM 'JOB_CLOSE' and close the job.
The submit stmt is working perfectly fine when executed directly..from R/3. The spool is also being created.
I tried debugging the same. This goes to the INITIALIZITION part of the program but no goin to START-OF-SELECTION.
Pls suggest if I am missing something in the code.
Thanks,
Teja.>
teja wrote:
> Hi,
>
> I am submitting report from WD. PFB the code i used. This is cuccessfully creating the JOB in SM37 and the status is 'Finished'. But when I click for the SPOOL, it is giving me an error 'No list available'.
>
> I used the following code for submitting the program.
>
>
> * call the FM 'JOB_OPEN' and create the job.
>
> SUBMIT ztest TO SAP-SPOOL
> WITH pnppernr-low EQ pernr
> WITH pnpbukrs-low EQ bukrs
> SPOOL PARAMETERS lv_print_parameters
> WITHOUT SPOOL DYNPRO
> VIA JOB lv_name NUMBER lv_number " job name and number created from JOB_OPEN
> AND RETURN.
>
> * call the FM 'JOB_CLOSE' and close the job.
>
>
> The submit stmt is working perfectly fine when executed directly..from R/3. The spool is also being created.
>
> I tried debugging the same. This goes to the INITIALIZITION part of the program but no goin to START-OF-SELECTION.
>
> Pls suggest if I am missing something in the code.
>
> Thanks,
> Teja.
Hi,
I guess this wont work. Didnt you get any dump ?
FM's with dialog screens,conversion exits would cause the webdynpro session to disconnect. -
hi all,
I am doing report in which there is opening stock , closing stock and all movement wise stock.
i am able to do all this for one material but when i am try for more than one material then value of last material is overwrite on other material.
I m using collect stmt to do sum for all movement.
plz help me.hi all,
plz see my code look like this :
TABLES : MSEG , MKPF , MAKT , MBEW.
DATA : BEGIN OF ITAB OCCURS 0,
LBKUM LIKE MSEG-LBKUM,
LBKUM1 LIKE MSEG-LBKUM,
MAKTX LIKE MAKT-MAKTX,
LGORT LIKE MSEG-LGORT,
BWART LIKE MSEG-BWART,
ZEILE LIKE MSEG-ZEILE,
MENGE LIKE MSEG-MENGE,
MEINS LIKE MSEG-MEINS,
MATNR LIKE MSEG-MATNR,
WERKS LIKE MSEG-WERKS,
SHKZG LIKE MSEG-SHKZG,
MBLNR LIKE MKPF-MBLNR,
BUDAT LIKE MKPF-BUDAT,
SIGN(2),
101_102 LIKE MSEG-MENGE,
END OF ITAB.
DATA : BEGIN OF ITAB_TOT OCCURS 0,
MATNR LIKE MSEG-MATNR,
LBKUM1 LIKE MSEG-LBKUM,
TOTAL1 LIKE MSEG-MENGE,
TOTAL1 TYPE P DECIMALS 3,
CLO TYPE P DECIMALS 3,
101_102 LIKE MSEG-MENGE,
END OF ITAB_TOT.
PARAMETERS : WERKS LIKE MSEG-WERKS DEFAULT 'BRHP' OBLIGATORY.
SELECT-OPTIONS : MATNR FOR MSEG-MATNR OBLIGATORY.
SELECT-OPTIONS: DAT FOR MKPF-BUDAT.
SELECT-OPTIONS: LGORT FOR MSEG-LGORT.
START-OF-SELECTION.
SELECT DISTINCT MSEG~MATNR
MSEG~LGORT
MSEG~BWART
MSEG~ZEILE
MSEG~MENGE
MSEG~MEINS
MSEG~WERKS
MSEG~LBKUM
MSEG~SHKZG
MKPF~MBLNR
MKPF~BUDAT
INTO CORRESPONDING FIELDS OF TABLE ITAB
FROM MSEG
INNER JOIN MKPF ON MSEG~MBLNR = MKPF~MBLNR
WHERE MSEG~MATNR IN MATNR
AND MSEG~LGORT IN LGORT
AND MSEG~WERKS EQ WERKS
AND mKPF~BUDAT IN DAT
AND MSEG~ZEILE = 1
order by mkpf~MBLNR.
LOOP AT ITAB.
IF ITAB-SHKZG = 'S'.
ITAB-SIGN = '+'.
MODIFY ITAB.
ELSE.
ITAB-SIGN = '-'.
MODIFY ITAB.
ENDIF.
ENDLOOP.
SORT ITAB BY MATNR.
LOOP AT ITAB.
IF ITAB-BWART = '121' OR ITAB-BWART = '122' .
SELECT MENGE INTO (ITAB-121_122) FROM MSEG WHERE MATNR =
ITAB-MATNR
AND MBLNR = ITAB-MBLNR
AND LGORT = ITAB-LGORT
AND WERKS = ITAB-WERKS.
AND ZEILE = ITAB-ZEILE.
MODIFY ITAB.
ENDSELECT.
ENDIF.
LOOP AT ITAB.
IF ITAB-SHKZG = 'H'.
ITAB-121_122 = ITAB-121_122 * -1.
MODIFY ITAB.
ELSE.
ITAB-121_122 = ITAB-121_122.
MODIFY ITAB.
ENDIF.
ENDLOOP.
ENDLOOP.
LOOP AT ITAB.
SELECT LBKUM INTO (ITAB-LBKUM) FROM MSEG WHERE MATNR = ITAB-MATNR
and
MBLNR = ITAB-MBLNR AND WERKS = ITAB-WERKS AND ZEILE = 1.
MODIFY ITAB.
ENDSELECT.
ENDLOOP.
SORT ITAB BY matnr mblnr.
LOOP AT ITAB.
IF ITAB[] IS NOT INITIAL.
DELETE ADJACENT DUPLICATES FROM ITAB COMPARING MATNR .
MOVE ITAB-lBKUM TO ITAB-LBKUM1.
MODIFY ITAB.
*APPEND ITAB_TOT1.
ENDIF.
ENDLOOP.
LOOP AT ITAB .
MOVE-CORRESPONDING ITAB TO ITAB_TOT.
COLLECT ITAB_TOT.
ENDLOOP.
loop at itab_tot.
write : / itab_tot-matnr , itab_tot-121_122 , itab-lbkum.
endloop.
i am not getting correct value of 121_122.
what should i do? -
Hello All,
May i know why the following example from Oracle documentation is failing.
CREATE TABLE coords (x NUMBER, y NUMBER);
CREATE TYPE Pair AS OBJECT (m NUMBER, n NUMBER);
DECLARE
TYPE PairTab IS TABLE OF Pair;
pairs PairTab := PairTab(Pair(1,2), Pair(3,4), Pair(5,6));
TYPE NumTab IS TABLE OF NUMBER;
nums NumTab := NumTab(1, 2, 3);
BEGIN
/* The following statement succeeds. */
FORALL i in 1..3
UPDATE coords SET (x, y) = (pairs(i).m, pairs(i).n)
WHERE x = nums(i);
END;
Error:
Error starting at line 37 in command:
DECLARE
TYPE PairTab IS TABLE OF Pair;
pairs PairTab := PairTab(Pair(1,2), Pair(3,4), Pair(5,6));
TYPE NumTab IS TABLE OF NUMBER;
nums NumTab := NumTab(1, 2, 3);
BEGIN
/* The following statement succeeds. */
FORALL i in 1..3
UPDATE coords SET (x, y) = (pairs(i).m, pairs(i).n)
WHERE x = nums(i);
END;
Error report:
ORA-06550: line 9, column 34:
PL/SQL: ORA-01767: UPDATE ... SET expression must be a subquery
ORA-06550: line 9, column 7:
PL/SQL: SQL Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
Thank you.Based on your advise i did the below example,
DECLARE
TYPE PairTab IS TABLE OF Pair;
pairs PairTab := PairTab(Pair(1,2), Pair(3,4), Pair(5,6),Pair(7,8),Pair(9,10));
TYPE NumTab IS TABLE OF NUMBER;
nums NumTab := NumTab(1,2,3,4,5);
vnum1 NUMBER;
vnum2 number;
BEGIN
FORALL i IN 1 .. 5
UPDATE coords
SET (x, y) = (SELECT pairs(i).m, pairs(i).n
FROM dual)
WHERE x = nums(i);
END;
INSERT INTO coords VALUES(1,10);
INSERT INTO coords VALUES(2,10);
insert into coords values(3,10);
INSERT INTO coords VALUES(4,10);
INSERT INTO coords VALUES(5,10);
commit;
After insertng the data into coords table i execute the above plsql block i got the below output.I wonder how come rows 2,3 & 5 are updated with 9,10.
Output:
1
2
9
10
9
10
7
8
9
10 -
***** in the output AT END stmt
I am getting ***** in the output, if I use the at end stmt. Can anybody tell me the reason and teh solution??
Hello,
When using AT END ENDAT all fields to the right of the current control key(Matnr in your case) will be filled with ****s. This means that you can do things like SUM on an amount or quantity field. If you need some of the character type fields at the AT END you will have to code around that.
eg (please note this is not syntactically accurate or complete code)
data ls_tmp like ls_itab.
loop at it_itab into ls_itab.
ls_tmp = ls_itab. " save current line of itab
at end matnr
do something ie sum or whatever your requirements are
write ls_tmp-charfield.
endat.
endloop.
Regards
Greg Kern -
Hi All,
I am using FORALL for inserting 40000 records from the file to the table. After reading data from the file it has been stored in type Table array, But while executing FORALL statement its giving ora-00600. error.
It is a memory error, some where I read to using LIMIT in fetch. But I am not using any fetch or Cursor. Can any body Help.
SKM
=================== ================= Package Code
create or replace package insertpackage as
TYPE tabSNO IS TABLE OF VARCHAR2(30) INDEX BY BINARY_INTEGER;
TYPE tabSNO1 IS TABLE OF VARCHAR2(1) INDEX BY BINARY_INTEGER;
TYPE tabSDATE IS TABLE OF VARCHAR2(20) INDEX BY BINARY_INTEGER;
TYPE SNO IS TABLE OF NUMBER(5) INDEX BY BINARY_INTEGER;
procedure insertpro(snoArray IN SNO, sDate IN tabSDATE, sArray IN tabSNO, sArray1 IN tabSNO1);
end insertpackage;
create or replace package body insertpackage as
procedure insertpro(snoArray IN SNO, sDate IN tabSDATE, sArray IN tabSNO, sArray1 IN tabSNO1) is
begin
forall i in 1..sArray.last
insert into test(s_no, s_date, s_co, s_type)
values(snoArray(i), TO_DATE(sDate(i),'YYYY-MM-DD HH24.MI.SS'), sArray(i), sArray1(i));
end;
end insertpackage;
/Hi User,
The error
implementation restriction: cannot reference fields of BULK In-BIND table of recordsis because bulk bind cannot use table of composite types.
Please See the below,
http://dba-blog.blogspot.com/2005/08/using-of-bulk-collect-and-forall-for.html
And rewrite your code like this,
DECLARE
CURSOR EMP_CUR
IS
SELECT EMPNO, ENAME
FROM EMP;
TYPE TAB_EMP_EMPNO IS TABLE OF EMP.EMPNO%TYPE;
V_TAB_EMPNO TAB_EMP_EMPNO;
TYPE TAB_EMP_ENAME IS TABLE OF EMP.ENAME%TYPE;
V_TAB_ENAME TAB_EMP_ENAME;
BEGIN
OPEN EMP_CUR;
FETCH EMP_CUR BULK COLLECT INTO V_TAB_EMPNO, V_TAB_ENAME;
FORALL I IN V_TAB_EMPNO.FIRST .. V_TAB_EMPNO.LAST
INSERT INTO EMP_TEMP
(EMPNO, ENAME
VALUES (V_TAB_EMPNO (I), V_TAB_ENAME (I)
CLOSE EMP_CUR;
END;Thanks,
Shankar -
Using Sequence in FORALL Statement
I'm using a package to get the nextval in a sequence object. Basically, it is a function that returns select user_seq.nextval from dual.
But I get 'column not allowed here' error. PL/SQL: ORA-00984: column not allowed here
OPEN users_ins ;
LOOP
FETCH naf_users_ins
BULK COLLECT
INTO arr_person_key
, arr_person_id
, arr_first_name
, arr_middle_name
, arr_last_name
, arr_username
, arr_user_status_seq
, arr_creation_date
, arr_comments
LIMIT 100 ;
FORALL idx IN 1 .. arr_person_key.COUNT
SAVE EXCEPTIONS
INSERT INTO users
( user_seq
, person_key
, person_id
, first_name
, middle_name
, last_name
, username
, user_status_seq
, creation_date
, comments
VALUES ( *pkg_admin.get_nextval*
, arr_person_key(idx)
, arr_person_id(idx)
, arr_first_name(idx)
, arr_middle_name(idx)
, arr_last_name(idx)
, arr_username(idx)
, arr_user_status_seq(idx)
, arr_creation_date(idx)
, arr_comments(idx)
EXIT WHEN users_ins%NOTFOUND ;
END LOOP ;
CLOSE users_ins;
c/code]Hi,
I've recently completed a similar task, but I declared a collection with the rowtype of the table. I also added the sequence in the query of my cursor. Take a look at the following example.
CREATE OR REPLACE PROCEDURE Insert_OR_ExternalService
IS
TYPE externalService_tbl IS TABLE OF OR_ExternalService%ROWTYPE;
externalService externalService_tbl;
CURSOR OR_ExternalServiceCursor
IS
select
SEQ_ID.NEXTVAL as "Id",
column as "ExternalId",
column as "ExternalSystem",
from table1
where ...;
BEGIN
OPEN OR_ExternalServiceCursor;
LOOP
FETCH OR_ExternalServiceCursor BULK COLLECT INTO externalService LIMIT 1000;
FORALL i IN 1 .. externalService.count
INSERT INTO OR_ExternalService values externalService(i);
COMMIT;
EXIT WHEN OR_ExternalServiceCursor%NOTFOUND;
END LOOP;
CLOSE OR_ExternalServiceCursor;
END; -
PLS-00435: DML statement without BULK In-BIND cannot be used inside FORALL
See code below: Have googled the error but not sure how to fix the code. ANy help would be most greatful.
DECLARE
CURSOR c1
IS
SELECT /*+ parallel(tr,8)*/ DISTINCT tr.ACC ACC, tr.MET_ID METID, to_char(max(TRUNC(PKG_LSR_IMPOSITION.convertXXMMDDToDate(tr.DATETR0))),'YYYY') dt
FROM CTTR0FIL_CDC tr
JOIN transaction_action_sd sd on (sd.TRANSACTION_CODE = tr.RESULT)
WHERE sd.ACTION_TYPE = 'PAYMENT'
and to_char(TRUNC(PKG_LSR_IMPOSITION.convertXXMMDDToDate(tr.DATETR0)),'YYYY') = '1987'
GROUP BY tr.ACC, tr.MET_ID, to_char(TRUNC(PKG_LSR_IMPOSITION.convertXXMMDDToDate(tr.DATETR0)),'YYYY');
SUBTYPE PAY_DATES IS c1%ROWTYPE;
TYPE TMP_TABLE IS TABLE OF PAY_DATES INDEX BY PLS_INTEGER;
TBROWS TMP_TABLE;
temp VARCHAR2(100);
Begin
DBMS_OUTPUT.ENABLE(10000);
OPEN c1;
LOOP
FETCH c1 BULK COLLECT INTO TBROWS LIMIT 1000;
FORALL i IN 1..TBROWS.COUNT
SELECT /*+ parallel(da,8)*/ da.ACC INTO temp
FROM CTDA0FIL_CDC da
WHERE da.ACC = TBROWS(i).ACC AND da.MET_ID = TBROWS(i).MET_ID AND da.ACC = '07000006P' AND da.MET_ID = 4;
DBMS_OUTPUT.PUT_LINE('inside');
EXIT WHEN c1%notfound;
END LOOP;
CLOSE c1;
END;
Thanks
SimonI tried using a normal for loop instead of a forall loop (see code below). But this came up the error also see below. Or can I not use selects in this way???
OPEN c1;
LOOP
FETCH c1 BULK COLLECT INTO tbrows LIMIT 1000;
FOR i IN TBROWS.FIRST .. TBROWS.LAST
LOOP
SELECT /*+ parallel(da,8)*/ da.ACC INTO temp
FROM CTDA0FIL_CDC da WHERE da.ACC = TBROWS(i).ACC AND da.MET_ID = TBROWS(i).MET_ID AND da.ACC = '07000006P' AND da.MET_ID = 4;
DBMS_OUTPUT.PUT_LINE('inside');
EXIT WHEN c1%notfound;
END LOOP;
END LOOP;
CLOSE c1;
END;
Error:
DECLARE
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error
ORA-06512: at line 24 -
Use of Select stmts with Update stmts
Hi,
I want to execute the following update stmt...
UPDATE Test1_tab a
SET a.invpln_seq_no = (SELECT b.seq_no
FROM Test2_tab b
WHERE b.contract_id = a.contract_id
AND b.date_from = a.period_from_date)
WHERE a.invpln_seq_no != (SELECT b.seq_no
FROM Test2_tab b
WHERE b.contract_id = a.contract_id
AND b.date_from = a.period_from_date)
Here the problem is I have used 'SELECT b.seq_no FROM Test2_tab b WHERE b.contract_id = a.contract_id AND b.date_from = a.period_from_date' twice, one in the SET clause and the other one in WHERE clause...But it is the same SELECT stmt...So this same Select stmt runs twice when I run the whole update stmt I guess. Is there a way to do the above update, where it runs the SELECT stmt only once...
Any input is highly appreciated...
Thanks And Best Regards,
/Dinesh...Then you can use Merge statement instead.
try this
merge into test1_tab t1
using
(SELECT a.rowid,b.seq_no SEQ_DEST
FROM test1_tab a,test2_tab b
WHERE b.contract_id = a.contract_id
AND b.date_from = a.period_from_date
AND a.invpln_seq_no != b.seq_no) t2
ON (t1.rowid=t2.rowid)
WHEN MATCHED THEN
UPDATE SET t1.invpln_seq_no=t2.seq_destor if you are sure that sno is a unique key with out any duplicates and if you are going to perform one time manual update then you can use an undocumented hint /*+ bypass_ujvc */ to do this.
*DO NOT include this code if you are about to add it in a production procedure or a function
UPDATE /*+ bypass_ujvc */ (SELECT a.invpln_seq_no SEQ_SRC,b.seq_no SEQ_DEST FROM test1_tab a,test2_tab b
WHERE b.contract_id = a.contract_id
AND b.date_from = a.period_from_date
AND a.invpln_seq_no != b.seq_no)
SET SEQ_SRC = SEQ_DESTRegards,
Prazy -
FORALL MERGE statement works in local database but not over database link
Given "list", a collection of NUMBER's, the following FORALL ... MERGE statement should copy the appropriate data if the record specified by the list exists on both databases.
forall i in 1..list.count
merge into tbl@remote t
using (select * from tbl
where id = list(i)) s
on (s.id = t.id)
when matched then
update set
t.status = s.status
when not matched then
insert (id, status)
values (s.id, s.status);
But this does not work. No exceptions, but target table's record is unchanged and "sql%rowcount" is 0.
If the target table is in the local database, the exact same statement works:
forall i in 1..list.count
merge into tbl2 t
using (select * from tbl
where id = list(i)) s
on (s.id = t.id)
when matched then
update set
t.status = s.status
when not matched then
insert (id, status)
values (s.id, s.status);
Does anyone have a clue why this may be a problem?
Both databases are on Oracle 10g.
Edited by: user652538 on 2009. 6. 12 오전 11:29
Edited by: user652538 on 2009. 6. 12 오전 11:31
Edited by: user652538 on 2009. 6. 12 오전 11:45Should throw an error in my opinion. The underlying reason for not working is basically because of
SQL> merge into t@remote t1
using ( select sys.odcinumberlist (1) from dual) t2
on (1 = 1)
when matched
then
update set i = 1
Error at line 4
ORA-22804: remote operations not permitted on object tables or user-defined type columnsSame reason as e.g.
insert into t@remote select * from table(sys.odcinumberlist(1,2,3))doesn't work.
Maybe you are looking for
-
I resized the adobe window to 150% and now I can't get it back to the 100% size and keep it that size. How do I get the original 100% back and keep it that size?
-
Reg:Standard And Movin Price change
Dear Sir, In Material master the standard price of a raw material is maintained as Rs 217 and moving price is maintained as Rs 210 I want to change the both price standard price as Rs 210 and moving price as Rs 208.How I will change this.In materi
-
Hello SAP Gurus, I received an iDoc status 51. I tried reposting the iDoc in the logical system using BD87. However, I still received the message: Logical system for CTR XX00/P8867920 inconsistent I had maintained and checked the Master Data for thi
-
I just did an update to Lion 10.7.4 with Safari 6.0. Now when I re-open Safari after closing it by clicking the red button, it re-opens to just my home page, not to all my previous tabs as it did before the update. I prefer having my old tabs re-
-
The music and video apps on my iPod touch (3rd generation, 32 gb) do not work but instead lead to a blank black screen. Safari and the other apps still work, but music and video don't. Anybody know how to troubleshoot?