Pl/sql block updating orderId, itemID
lol here i am again!
This time its like this:
i have a table (orderId, itemId, CustomerId, productId, quantity, start_date, end_date, oldRef)
here are some of the values:
2477, 1, 201, 111, 1,19-MAR-93,14-APR-93
2477,2,201,112,1,19-MAR-93,14-APR-93
2478,1,201,113,1,19-MAR-93,14-APR-93
2478,2,201,110,19-Mar-93,14-APR-93
Now as you can see that order_Id is different however order_date and ship_date both match. Now what i want to do is to give them a new orderId, re-arrange itemId if ship_date and order_date match for each customer so the ex above should come out like this:
1, 1, 201, 111, 1,19-MAR-93,14-APR-93
1,2,201,112,1,19-MAR-93,14-APR-93
1,3,201,113,1,19-MAR-93,14-APR-93
1,4,201,110,19-Mar-93,14-APR-93
I have created a pl/sql block. It has a cursor that loops around each row of table. Then it stores orderdate, shipdate and customerId. it also has a itemId variable and orderDate variable. OrderDate variable takes its value from orderId sequence and itemId is just a number that increments itself.
NOW when orderdate,shipdate&customerId are the same, i just update the itemId, if they differ or customer_id changes i get a new order_id, update the variables (orderdate,shipdate,customerid,itemId) but for some reason i dont think it is working!!
DECLARE
cursor c1 is
SELECT
FROM
ph2_item
order by
customer_id,
ship_date,
order_date
for update;
new_order_id number(8,0) := 0;
new_item_id number(4,0) := 1;
temp_odate date := '11-JUN-08';
temp_sdate date:= '11-JUN-08';
temp_cId number(8,0) := 1;
BEGIN
FOR rec in c1 LOOP
IF rec.customer_id = temp_cId THEN
IF (rec.order_date <> temp_odate OR
rec.ship_date <> temp_sdate) THEN
new_item_id:= 1;
SELECT orderid.nextVal into new_order_id from dual;
temp_odate :=rec.order_date;
temp_sdate :=rec.ship_date;
END IF;
ELSE
new_item_id:= 1;
SELECT orderid.nextVal into new_order_id from dual;
temp_cid := rec.customer_id;
temp_odate :=rec.order_date;
temp_sdate :=rec.ship_date;
END IF;
update ph2_item
set order_id = new_order_id, item_id = new_item_id
where current of c1;
new_item_id := new_item_id + 1;
END LOOP;
END;
commit;PS> this is not a real life database and just a college assignment!
just corrected a mistake in one of the example code i posted
Message was edited by:
user646562
well it does seem to give the right results ie. orderId is changed and itemId is rearranged! however the college has an online marker and when i try to submit the code, it says that the max(order_id) of the resulting table (ph2_item) is wrong, the sum(item_id) is wrong and the no of distinct orders is wrong.. this means i am either consolidating orders whne i shouldnt, and this in turns make my item_id wrong..
also there is one more criteria i should have mentioned but i forgot and that is even if the order_date and ship_date is the same as another order, we will only consolidate them if the customer in question has multiple sites.
here is the updated pl/sql block taking into account this criteria (using if/else statement)
DECLARE
cursor c1 is
SELECT
FROM
ph2_item
order by
order_date,
customer_id
for update;
new_order_id number(8,0) := 0;
new_item_id number(4,0) := 1;
temp_odate date := '11-JUN-08';
temp_sdate date:= '11-JUN-08';
temp_cId number(8,0) := 1;
totalSites number(2,0);
BEGIN
FOR rec in c1 LOOP
select site_count into totalsites from customer_sites where customer_id = rec.customer_id;
--dbms_output.put_line(rec.customer_id ||' ' || totalsites);
if totalsites > 1 THEN
IF rec.customer_id = temp_cId THEN
IF (rec.ship_date <> temp_sdate AND rec.order_date <> temp_odate) AND rec.ship_date is null THEN
new_item_id:= 1;
SELECT orderid.nextVal into new_order_id from dual;
temp_odate :=rec.order_date;
--temp_sdate :=rec.ship_date;
END IF;
ELSE
new_item_id:= 1;
SELECT orderid.nextVal into new_order_id from dual;
temp_cid := rec.customer_id;
temp_odate :=rec.order_date;
--temp_sdate :=rec.ship_date;
END IF;
ELSE
new_item_id:= 1;
SELECT orderid.nextVal into new_order_id from dual;
temp_cid := rec.customer_id;
temp_odate :=rec.order_date;
--temp_sdate :=rec.ship_date;
END IF;
update ph2_item
set order_id = new_order_id, item_id = new_item_id
where current of c1;
new_item_id := new_item_id + 1;
END LOOP;
END;
Similar Messages
-
Alter table then Update in PL/SQL block
I am trying to alter the table then update it :
declare
colCount number;*
begin*
select count(*) into colCount from all_tab_cols where table_name = 'TEST' and owner = 'TEST_OWNER';*
dbms_output.put_line('No of Columns in the table : ' || colCount);*
if colCount = 2 then*
dbms_output.put_line('Table needs upgrade');*
execute immediate('ALTER TABLE TEST ADD COL1 VARCHAR2(100) NULL');*
UPDATE TEST SET COL1 = '123';*
commit;*
else*
dbms_output.put_line('No Changes Required');*
end if;*
end;*
Oracle complains that "COL1" is an invalid identifier.
I also tried substitute the UPDATE statement with
** execute immediate('UPDATE TEST SET VCHCHARSET_OUT='UTF8' WHERE VCHCHARSETNAME='UTF8'');**
and there is something wrong with the construction of an Update statement in the parenthesis.
Am I taking the right approach and just need to figuire out the syntax of single quotes or something else is wrong?
thanks in advance.Yes, you are absolutely right, I shouldn't alter the table and then update the values.
The reason I need to do it relates to the migration process we utilize in our company. Initially I had a set of SQL commands which I executed migrating from one environment to another and eventually to Production. I had an error in the last SQL command which caused migration process to produce "Failure", however the table was already altered and all the rows except the last one were updated. Since I can't successfully migrate to Production with the failed process I have to generate a PL/SQL block which will take in consideration that in one environment the table has already been modified and in the other one is still needs to be changed. -
Update Statement(with Case) in PL/SQL Block
Can we use Oracle case syntax (In a Update SQL)in a PL/SQL Block .
UPDATE table_name a
SET a.colum1 =
case when a.col2 IN (SELECT col1
FROM table_name1 b )
then 'Y'
else 'N'
end
It throws me an Error of code PLS-00103(This error message is from the parser. It found a token (language element) that is inappropriate in this context.)
Is there any alternative...
Thanx in Advance
nullAlas, PL/SQL has own SQL parser, and this parser dosn't know about CASE expressions (at least, it's true up to Oracle 8.1.7).
Try to use DECODE instead, something like
UPDATE table_name a
SET a.colum1 =
SELECT decode(count(*),0,'N','Y)
FROM table_name1 b
WHERE b.col1=a.colum1 -
Write an UPdate statement using the logic used in PL/SQL block (oracle 10g)
Hi All,
I have written the following PL/SQL block. I want to write an UPDATE statement using the logic used in the following PL/SQL block. can any one please help me out in this regards.
DECLARE
v_hoov_fag gor_gold_post.hoov_flg%TYPE;
v_b49n gor_gold_post.b49n%TYPE;
CURSOR c
IS
SELECT bs_id, loyalty_date, loyalty_period, contract_date
FROM gor_gold_post
WHERE tariff_code IN (169, 135, 136);
BEGIN
FOR rec IN c
LOOP
IF (TRUNC (ADD_MONTHS (rec.loyalty_date, rec.loyalty_period)
- SYSDATE) < 304
OR ( TRUNC ( ADD_MONTHS (rec.loyalty_date, rec.loyalty_period)
- SYSDATE
) IS NULL
AND (SYSDATE - TO_DATE (rec.contract_date, 'YYYYMMDD')) > 91.2
THEN
v_hoov_flg := 1;
ELSE
v_hoover_flag := 99;
END IF;
IF (TRUNC (ADD_MONTHS (rec.loyalty_date, rec.loyalty_period)
- SYSDATE) < 121.6
OR ( TRUNC ( ADD_MONTHS (rec.loyalty_date, rec.loyalty_period)
- SYSDATE
) IS NULL
AND (SYSDATE - TO_DATE (rec.contract_date, 'YYYYMMDD')) > 91.2
THEN
v_b49n := 1;
ELSE
v_b49n := 99;
END IF;
UPDATE gor_gold_post
SET hoov_flg = v_hoov_flg,
b49n = v_b49n
WHERE bs_id = rec.bs_id AND tariff_code IN (169, 135, 136);
COMMIT;
END LOOP;
END;Thank you,Using case statement.
UPDATE gor_gold_post
SET hoov_flag = CASE WHEN TRUNC (ADD_MONTHS (rec.loyalty_date, rec.loyalty_period) - SYSDATE) < 304
OR
(TRUNC (ADD_MONTHS (rec.loyalty_date, rec.loyalty_period) - SYSDATE) IS NULL
AND (SYSDATE - TO_DATE (rec.contract_date, 'YYYYMMDD')) > 91.2)
THEN 1
ELSE 99
END,
b49n = CASE WHEN TRUNC (ADD_MONTHS (rec.loyalty_date, rec.loyalty_period) - SYSDATE) < 121.6
OR
(TRUNC (ADD_MONTHS (rec.loyalty_date, rec.loyalty_period) - SYSDATE) IS NULL
AND (SYSDATE - TO_DATE (rec.contract_date, 'YYYYMMDD')) > 91.2)
THEN 1
ELSE 99
END
WHERE tariff_code IN (169, 135, 136);Note: Code not tested. -
How to convert pl/sql block into single update statement
Dear all gurus,
I have pl/sql block mention below, Can I convert this pl/sql block to single update statement if possible?
If not how to optimize this block?
Pleaese suggest.
thanks in advance.
Vijay
DECLARE
CURSOR vt_mlr_cursor IS Select master_key, user4 from vt_mlr Where USER4 is not null;
USERFIELD VARCHAR2(100);
C1 VARCHAR2(3); /* this will return location of first space = 12 */
C2 VARCHAR2(3); /* this will return location of second space = 20 */
C3 VARCHAR2(3); /* this will return location of third space = 28 */
C4 VARCHAR2(3); /* this will return location of forth space = 35 */
Field1 VARCHAR2(40); /* this will return FTMYFLXA04W */
Field2 VARCHAR2(10); /* this will return VPI0043 */
Field3 VARCHAR2(10); /* this will return VCI0184 */
Field4 VARCHAR2(10); /* this will return 005 */
Field5 VARCHAR2(10); /* this will return 00001 */
Field_2_n_3 VARCHAR2(25);
key VARCHAR2(10);
BEGIN
FOR vt_mlr_record IN vt_mlr_cursor
LOOP
key := vt_mlr_record.master_key;
USERFIELD := vt_mlr_record.user4;
C1 := INSTR(vt_mlr_record.user4,' ',1,1); /* this will return location of first space = 12 */
C2 := INSTR(vt_mlr_record.user4,' ',1,2); /* this will return location of second space = 20 */
C3 := INSTR(vt_mlr_record.user4,' ',1,3); /* this will return location of third space = 28 */
C4 := INSTR(vt_mlr_record.user4,' ',1,4); /* this will return location of forth space = 35 */
Field1 := SUBSTR(vt_mlr_record.user4,1,C1-1); /* this will return FTMYFLXA04W */
Field2 := SUBSTR(vt_mlr_record.user4,C1+4,C2-C1-4); /* this will return VPI0043 */
Field3 := SUBSTR(vt_mlr_record.user4,C2+4,C3-C2-4); /* this will return VCI0184 */
Field4 := SUBSTR(vt_mlr_record.user4,C3+4,C4-C3-4); /* this will return 005 */
Field5 := SUBSTR(vt_mlr_record.user4,C4+4,LENGTH(vt_mlr_record.user4)-C4-3); /* this will return 00001 */
Field_2_n_3 := Field2 || '/' || Field3;
/*DBMS_OUTPUT.PUT_LINE ('Current key is: ' || vt_mlr_record.master_key);*/
UPDATE vt_mlr
SET
aggregator_clli = Field1,
aggregator_vpi_vci = Field_2_n_3,
aggregator_slot = Field4,
aggregator_port = Field5
WHERE
master_key = vt_mlr_record.master_key;
END LOOP;
END;
/Hi Vijay,
Here's something to start with, you should be able to complete it.
First, combine your select and update statements:
update vt_mlr
set aggregator_clli = field1
,aggregator_vpi_vci = field_2_n_3
,aggregator_slot = field4
,aggregator_port = field5
where user4 is not null;Then put these two
C1 := INSTR(vt_mlr_record.user4,' ',1,1);
Field1 := SUBSTR(vt_mlr_record.user4,1,C1-1);into
Field1 := SUBSTR(vt_mlr_record.user4,1,INSTR(vt_mlr_record.user4,' ',1,1) -1);And put it into the update statement, removing reference to record
(I have also removed default values for position and occurrence in instr function):
update vt_mlr
set aggregator_clli = substr(user4, 1, instr(user4,' ') - 1)
,aggregator_vpi_vci = field_2_n_3
,aggregator_slot = field4
,aggregator_port = field5
where user4 is not null; I think you can do the rest from here ;-)
Regards
Peter -
How to update PL/SQL block/Specs in Repository without cut/paste ?
(cross-posted in METALINK form also)
Hello,
Question: How to quickly update PL/SQL block/specs in a package
Repository Object Browser? (without cut/paste)
Tools: Designer 9i, ROB 9.0.2.6
Detailed description of a problem:
-- there is no good pl/sql IDE working with ROB
(JDeveloper can not work with NOT PRIVATE repository workspace)
-- I use Toad and develop/generate pl/sql object
directly in database.
-- I have to synchronize my work with repository as often
as possible the following way (we do not use read-server model
because afraid of getting 1000s of atomik func and proc):
---- navigate to the pl/sql package
---- select properties
---- click on pl/sql block - get old code in editor
---- copy all new code from Toad into editor
---- remove CREATE OR REPLACE and last line
---- save
---- do the same with specifications
I am looking for some way to do this with some script or
one-button click...
For example, for text files it is possible to use command line
Repository Tool. But I did not found the possibility to make
a script like this:
checkout
update workarea/container/plsql_definition/package_name/body....
.....with new_package_body.txt
checkin
Thanks in advance for any help/advice,
Alex V.Hi Alex,
I just had an "Ah! I see!" moment. I now understand why you're having trouble and I can explain things so you can move on... I hope!
First it's important to understand that Oracle SCM is designed to support versioning of both files and Oracle Designer objects. Designer objects are stored as rows in specially structured tables that support that specific product. When you look at PL/SQL definitions in the RON you're looking at Designer definitions - not files. As I mentioned before, these are not the definitions of 'real' PL/SQL objects in the data dictionary, but definitions used by Designer (from which the real things can be generated - but that's another story).
If you're using TOAD you should probably avoid accessing the Designer objects. You need to work with files.
Here's a suggestion for a sequence of operations:
- In the RON check out & download the file (e.g. mypkg.plb)
- In TOAD load the package (from DB, or downloaded file), edit, update package in DB
- In TOAD save as mypkg.plb (overwriting the downloaded copy)
- IN RON upload mypkg.plb and check in
If you've not stored the file in Oracle SCM yet, jsut omit the first step.
You could even automate this to an extent using SQL to query the data dictionary views (e.g. USER_SOURCE) after making changes to get the code and edit/overwrite the file contents that way.
Does this help at all?
Keith. -
Can some one please tell me what is the problem in the below pl/sql block
Hi, I have problem with the following pl/sql block, I need this with bulk operation.
-- Assume the following scenario, we are validating dept (master) and emp(child) which are my temporary tables and updating the status back to
-- dept ( for all the validation errors, even if we have any validation at child it has to update the header record with error message),
-- upon successful validation insert the data into dept3, and emp3 interms of batches
-- I have give the sample example with dept and emp, but i have around 10 million records which has around 30-40 validations,
-- I would like to process them in terms of batches using bulk collection as this would do fast processing
-- Can some one please tell me how to insert them in terms of bulk with every set of 1000 records in each batch in this example,for every set of 1000 records
-- i need update batch id with unique number in dept table
-- with current data i can have 50 batches , I need to pass, deptno as parameter to my emp cursor.
-- can some one please tell me how to make this validation and insertion more efficient. so that while inserting the data for every batch it should insert batch id
-- Tried with LIMIT clause as well but not working
-- I am correcting the code as per your comments Request you to please suggest me so that I can correct , I am new to PL/sql, started learning now.
step - 1:
CREATE TABLE DEPT
(DEPTNO NUMBER(6) primary key,
DNAME VARCHAR2(25),
LOC VARCHAR2(23),
batch_id number );
INSERT INTO DEPT VALUES (10, 'ACCOUNTING', 'NEW YORK', null);
INSERT INTO DEPT VALUES (20, 'RESEARCH', 'DALLAS', null);
INSERT INTO DEPT VALUES (30, 'SALES', 'CHICAGO', null);
INSERT INTO DEPT VALUES (40, 'OPERATIONS', 'BOSTON', null);
step - 2:
declare
begin
for i in 1..50000 loop
insert into dept values(40+i, 'OPERATIONS'||i,'BOSTON'||i, null);
end loop;
commit;
exception
when others then
dbms_output.put_line('Exception occured:'||SQLERRM);
end;
step - 3:
create sequence emp_seq start with 1 increment by 1;
step - 4:
CREATE TABLE EMP
(EMPNO NUMBER(15) NOT NULL primary key,
ENAME VARCHAR2(20),
JOB VARCHAR2(20),
MGR NUMBER(4),
HIREDATE DATE,
SAL NUMBER(7, 2),
COMM NUMBER(7, 2),
DEPTNO NUMBER(6));
INSERT INTO EMP VALUES
(7369, 'SMITH', 'CLERK', 7902,
TO_DATE('17-DEC-1980', 'DD-MON-YYYY'), 800, NULL, 20);
INSERT INTO EMP VALUES
(7499, 'ALLEN', 'SALESMAN', 7698,
TO_DATE('20-FEB-1981', 'DD-MON-YYYY'), 1600, 300, 30);
INSERT INTO EMP VALUES
(7521, 'WARD', 'SALESMAN', 7698,
TO_DATE('22-FEB-1981', 'DD-MON-YYYY'), 1250, 500, 30);
INSERT INTO EMP VALUES
(7566, 'JONES', 'MANAGER', 7839,
TO_DATE('2-APR-1981', 'DD-MON-YYYY'), 2975, NULL, 20);
INSERT INTO EMP VALUES
(7654, 'MARTIN', 'SALESMAN', 7698,
TO_DATE('28-SEP-1981', 'DD-MON-YYYY'), 1250, 1400, 30);
INSERT INTO EMP VALUES
(7698, 'BLAKE', 'MANAGER', 7839,
TO_DATE('1-MAY-1981', 'DD-MON-YYYY'), 2850, NULL, 30);
INSERT INTO EMP VALUES
(7782, 'CLARK', 'MANAGER', 7839,
TO_DATE('9-JUN-1981', 'DD-MON-YYYY'), 2450, NULL, 10);
INSERT INTO EMP VALUES
(7788, 'SCOTT', 'ANALYST', 7566,
TO_DATE('09-DEC-1982', 'DD-MON-YYYY'), 3000, NULL, 20);
INSERT INTO EMP VALUES
(7839, 'KING', 'PRESIDENT', NULL,
TO_DATE('17-NOV-1981', 'DD-MON-YYYY'), 5000, NULL, 10);
INSERT INTO EMP VALUES
(7844, 'TURNER', 'SALESMAN', 7698,
TO_DATE('8-SEP-1981', 'DD-MON-YYYY'), 1500, NULL, 30);
INSERT INTO EMP VALUES
(7876, 'ADAMS', 'CLERK', 7788,
TO_DATE('12-JAN-1983', 'DD-MON-YYYY'), 1100, NULL, 20);
INSERT INTO EMP VALUES
(7900, 'JAMES', 'CLERK', 7698,
TO_DATE('3-DEC-1981', 'DD-MON-YYYY'), 950, NULL, 30);
INSERT INTO EMP VALUES
(7902, 'FORD', 'ANALYST', 7566,
TO_DATE('3-DEC-1981', 'DD-MON-YYYY'), 3000, NULL, 20);
INSERT INTO EMP VALUES
(7934, 'MILLER', 'CLERK', 7782,
TO_DATE('23-JAN-1982', 'DD-MON-YYYY'), 1300, NULL, 10);
commit;
step :- 5
declare
cursor c1 is select * from dept;
k number:=0;
m number:=0;
begin
for i in c1 loop
k:=k+1;
--dbms_output.put_line('k:'||k);
--dbms_output.put_line('i.deptno:'||i.deptno);
m:=0;
for j in 1..5 loop
m:=m+1;
--dbms_output.put_line('m:'||m);
--dbms_output.put_line('i.deptno:'||i.deptno);
insert into emp values
(9000+emp_seq.nextval, 'SMITH'||'_'||emp_seq.currval, 'CLERK'||'_'||emp_seq.currval, 7902,
TO_DATE('17-DEC-1980', 'DD-MON-YYYY'), 800, NULL, i.deptno);
end loop;
end loop;
commit;
exception
when others then
dbms_output.put_line('Exception occured:'||sqlerrm);
end;
step :-6
create table dept3 as select * from dept where 1=2;
create table emp3 as select * from emp where 1=2;
alter table dept add object_id number;
alter table dept add status varchar(20);
alter table dept add err_msg varchar2(200);
alter table emp add object_id number;
-- I have not included the alter statements in the inital creation because i dont want them to insert into dept3 and emp3
CREATE OR REPLACE
PACKAGE test_b
AS
g_batch_id NUMBER;
PROCEDURE emp_ins(
p_EMPNO NUMBER,
p_ENAME VARCHAR2,
p_JOB VARCHAR2,
p_MGR NUMBER,
p_HIREDATE DATE,
p_SAL NUMBER,
p_COMM NUMBER,
p_DEPTNO NUMBER);
PROCEDURE dept_ins(
p_DEPTNO NUMBER,
p_dname VARCHAR2 ,
p_LOC VARCHAR2,
p_batch NUMBER);
PROCEDURE validate_prc;
PROCEDURE main;
TYPE dept_t
IS
TABLE OF dept%ROWTYPE;
hdr_tbl dept_t;
TYPE emp_t
IS
TABLE OF emp%ROWTYPE;
line_tbl emp_t;
TYPE dept_i_t
IS
TABLE OF dept3%ROWTYPE;
hdr_ins_tbl dept_i_t;
TYPE emp_i_t
IS
TABLE OF emp3%ROWTYPE;
line_ins_tbl emp_i_t;
END;
-- pacakge body
CREATE OR REPLACE
PACKAGE body test_b
AS
PROCEDURE emp_ins(
p_EMPNO NUMBER,
p_ENAME VARCHAR2,
p_JOB VARCHAR2,
p_MGR NUMBER,
p_HIREDATE DATE,
p_SAL NUMBER,
p_COMM NUMBER,
p_DEPTNO NUMBER)
IS
BEGIN
INSERT
INTO EMP3
EMPNO ,
ENAME ,
JOB ,
MGR ,
HIREDATE ,
SAL ,
COMM ,
DEPTNO
VALUES
P_EMPNO ,
P_ENAME ,
P_JOB ,
P_MGR ,
P_HIREDATE ,
P_SAL ,
P_COMM ,
P_DEPTNO
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('EXCEPTION AT EMP INSERT'||SQLERRM);
END;
PROCEDURE dept_ins
p_DEPTNO NUMBER,
p_dname VARCHAR2 ,
p_LOC VARCHAR2,
p_batch NUMBER
IS
BEGIN
INSERT
INTO DEPT3
DEPTNO ,
DNAME ,
LOC ,
batch_id
VALUES
p_DEPTNO ,
p_DNAME ,
p_LOC ,
p_batch
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('EXCEPTION AT DEPT INSERT'||SQLERRM);
END ;
PROCEDURE validate_prc
IS
CURSOR c1
IS
SELECT * FROM dept WHERE status IS NULL ;--AND rownum <25;
CURSOR c2(p_dept NUMBER )
IS
SELECT * FROM emp WHERE deptno=p_dept;
e_validation EXCEPTION;
BEGIN
OPEN c1;
LOOP
FETCH c1 BULK COLLECT INTO hdr_tbl limit 5000;
SELECT emp_seq.nextval INTO g_batch_id FROM dual;
EXIT
WHEN hdr_tbl.count = 0;
dbms_output.put_line('batch'||g_batch_id);
END LOOP;
CLOSE c1;
dbms_output.put_line('C1 closed');
--------- Loading data into the inv line table type -------------------------------
FOR i IN 1 .. hdr_tbl.count
LOOP
dbms_output.put_line('started validation');
-- do header level validations
IF hdr_tbl(i).dname IS NULL THEN
hdr_tbl(i).status := 'ERROR';
hdr_tbl(i).err_msg :=',DNAME is null';
END IF;
OPEN c2(hdr_tbl(i).deptno);
LOOP
FETCH c2 BULK COLLECT INTO line_tbl;
-- EXIT WHEN c2%NOTFOUND;
END LOOP;
CLOSE c2;
FOR j IN 1 .. line_tbl.count
LOOP
-- do line validations
IF line_tbl(j).ename IS NULL THEN
hdr_tbl(i).status := 'ERROR';
hdr_tbl(i).err_msg :=',ENAME is null';
END IF;
BEGIN
FORALL j IN line_tbl.FIRST .. line_tbl.LAST
SAVE EXCEPTIONS
UPDATE EMP
SET object_id =3
-- I have multiple columns to update based on validations
WHERE deptno =hdr_tbl(i).deptno------------
AND empno =line_tbl (j).empno;
COMMIT;
line_tbl.DELETE;
dbms_output.put_line( 'Successfully updated emp temp table.');
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
dbms_output.put_line( 'Error while updating line temp table. ' || sqlerrm );
FOR j IN 1 .. sql%BULK_EXCEPTIONS.COUNT
LOOP
DBMS_OUTPUT.put_line(' occurred during line temp table updation ' || sql%BULK_EXCEPTIONS(i).ERROR_INDEX );
END LOOP;
raise e_validation;
END;
END LOOP; -- j
--CLOSE c2;
IF hdr_tbl(i).err_msg IS NULL THEN
hdr_tbl (i).status := 'VALID';
hdr_tbl (i).err_msg := NULL;
END IF;
-- even if I have line validation failed I have to update header status and erorr msg
BEGIN
FORALL i IN hdr_tbl.FIRST .. hdr_tbl.LAST
SAVE EXCEPTIONS
UPDATE DEPT
SET object_id =4,
status = hdr_tbl (i).status,
err_msg = hdr_tbl (i).err_msg
-- batch_id =
-- I have multiple columns to update based on validations
WHERE deptno = hdr_tbl (i).deptno
AND status IS NULL; ------------
COMMIT;
hdr_tbl.DELETE;
dbms_output.put_line( 'Successfully updated dept temp table.');
--close c1;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
dbms_output.put_line( 'Error while updating hdr temp table. ' || sqlerrm );
FOR i IN 1 .. sql%BULK_EXCEPTIONS.COUNT
LOOP
DBMS_OUTPUT.put_line(' occurred during line temp table updation ' || sql%BULK_EXCEPTIONS(i).ERROR_INDEX );
END LOOP;
raise e_validation;
END;
END LOOP; --i
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('EXCEPTION AT validate'||SQLERRM);
END ;
PROCEDURE main
IS
CURSOR dept_ins_cur
IS
SELECT * FROM dept WHERE status='VALID';
CURSOR emp_ins_cur(p_deptno NUMBER)
IS
SELECT * FROM emp WHERE deptno= p_deptno;
BEGIN
validate_prc;
OPEN dept_ins_cur;
LOOP
FETCH dept_ins_cur BULK COLLECT INTO hdr_ins_tbl limit 1000
EXIT
WHEN dept_ins_cur%NOTFOUND;
END LOOP;
CLOSE dept_ins_cur;
--------- Loading data into the inv line table type -------------------------------
FOR i IN 1 .. hdr_tbl.count
loop
dept_ins(hdr_ins_tbl(i).deptno ,
hdr_ins_tbl(i).DNAME ,
hdr_ins_tbl(i).LOC , emp_seq.nextval);
commit;
OPEN emp_ins_cur(hdr_ins_tbl(i).deptno);
LOOP
FETCH emp_ins_cur BULK COLLECT INTO line_ins_tbl;
--EXIT WHEN emp_ins_cur%NOTFOUND;
END LOOP;
CLOSE emp_ins_cur;
for j in 1..line_ins_tbl.count loop
emp_ins(line_ins_tbl(j).EMPNO ,
line_ins_tbl(j).ENAME ,
line_ins_tbl(j).JOB ,
line_ins_tbl(j).MGR ,
line_ins_tbl(j).HIREDATE ,
line_ins_tbl(j).SAL ,
line_ins_tbl(j).comm ,
line_ins_tbl(j).DEPTNO );
end loop;
end loop;
commit;
BEGIN
forall i IN hdr_ins_tbl.first .. hdr_ins_tbl.last
SAVE exceptions
UPDATE dept
SET status = 'INSERTED',
err_msg = null
WHERE deptno=hdr_ins_tbl (i).deptno
AND status = 'VALID';
COMMIT;
hdr_ins_tbl.delete;
dbms_output.put_line( 'inserting into temp tables.');
EXCEPTION
WHEN OTHERS THEN
rollback;
end;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('exception in main' ||SQLERRM);
END ;
END;
Thanks in advance...
Message was edited by: 888025Hi, I have problem with the following pl/sql block
Well, as Hoek already said, that is the understatement of the century.
I can't be absolutely certain but I think that set of DDL and code that you posted has just about every possible error and design issue that there is! It would make an excellent addition to BluShadow's FAQs an an example of what NOT to do.
I don't think it is even possible to 'fix the basics first' as Hoek suggested. IMHO the first step needs to be to create a functional requirements document (FRD) that explains in detail WHAT needs to be done. That doc should also contain info about how any errors/recovery/restart is to be handled. It is premature to try to implement ANY solution without first knowing what is needed functionally.
Once the FRD is done you should do a walk-through based on your current architecture and sample data to make sure that the document really covers ALL of the steps that need to be performed and that it adequately explains how to deal with any processing or data issues that might arise.
The next document you need is the TRD - Technical Requirements Doc that covers the different technical implementions of the FRD that can be done and the advantages/disadvantages of each.
Then you can start working on a prototype.
1. The DDL you posted isn't coherent - there are CREATE table statements and then later ALTER statements that add additional columns. There doesn't appear to be any reason for not including ALL of the columns in the CREATE table statement.
2. You are using PL/SQL types instead of SQL types. That makes it impossible to use those types in SQL statements and makes it much more difficult to test since it is much easier to test a query in SQL (e.g. using sql*plus) that to embed the query in PL/SQL.
3. You are defining the same type twice but giving it different names.
TYPE dept_t
IS
TABLE OF dept%ROWTYPE
INDEX BY binary_integer;
TYPE dept_i_t
IS
TABLE OF dept%ROWTYPE
INDEX BY binary_integer;
Those are both based on the same DEPT table! Why the duplication?
Also you are using associative arrays instead of just using nested tables. Get rid of the INDEX BY clause.
4. You have some serious architectural and data model issues
-- Assume the following scenario, we are validating dept (master) and emp(child) which are my temporary tables and updating the status back to
-- dept ( for all the validation errors, even if we have any validation at child it has to update the header record with error message),
Why would you do that? You say 'it has to update the header record ...'. Says who? That is just one indication that you are trying to implement a 'solution' before you have adequately defined the 'problem'.
Typically you would NOT alter any of the data tables; any validation errors/issues would get inserted into a table specifically designed to hold/log those issues. That table would contain key field values to correlate with the source of the error.
Those 'master' and 'child' entities are two SEPARATE things. Issues with a 'master' row have NOTHING to do with any possible child rows.
And issues with a 'child' row have NOTHING to do with any possible master rows. The ONLY connection between 'child' and 'master' is the foreign key that correlates them.
So you don't necessarily have to validate the 'child' rows in sync with their 'master' row. In many cases you would have a procedure that performs validation of the entire set of 'master' rows and log those issues/problems. You would use a different procedure to validate the entire set of 'child' rows and log their issues.
Those validation procedures can often work with ALL of the data using SQL statements instead of bulk processing.
5. You are using loop constructs that are not valid for the type of processing you are using
LOOP
FETCH c1 BULK COLLECT INTO hdr_tbl;
EXIT
WHEN c1%NOTFOUND;
END LOOP;
There can be NO exit since the bulk collect with either get EVERYTHING or NOTHING. Possibly that is just a holdover from your attempt to use the LIMIT clause but you removed that clause from the FETCH; I don't know.
There is so much wrong with what you posted it is really rather pointless to try to 'fix' it.
I suggest you start over and clarify and DOCUMENT the actual requirements without prejudice about the solution that someone seems to want to force on you. -
How to print/store in file the ref cursor in pl/sql block ?
How to print/store in file the ref cursor in pl/sql block ?.
How to print/store in file the ref cursor in pl/sql block ?.You question is quite confusing?
So, i'm providing link in this manner.
For RefCursor,
http://www.oracle-base.com/articles/misc/UsingRefCursorsToReturnRecordsets.php
http://www.oracle.com/technology/oramag/code/tips2003/042003.html
For UTL_FILE,
http://www.morganslibrary.org/reference/utl_file.html
Regards.
Satyaki De.
Updated with new morgan library link.
Edited by: Satyaki_De on Feb 24, 2010 9:03 PM -
PL SQL block - Check for empty file
Hello,
I need help in writing pl sql code to check a file to verify if it has 0 records (file size = zero kb.) In a preceding pl sql block, I am performing a SELECT on data and writing it to a file. If that file is empty/has no records, then I would like to stop the process from continuing on to my next pl sql block which performs an update function.
Summary:
1) Create file from SELECT
2) Check file for zero data, if true, trigger error, if false, continue to next pl sql block.
3) Run update on records if data exists in the file.
Thanks in advance!Thanks John,
You've been of great help so far and a really appreciate it. I'm so close to getting this, I just need help with how to create an error when the file shows no data. I will be running this as an Oracle Apps Concurrent request. I'd like for the job to end in error when no data exists for the file. In unix, I can enter "EXIT 1" and it signals to the concurrent manager to put end the job with an error status. How can I do something similar using pl sql? Here is my code so far, with the missing piece. Thanks!
DECLARE
vFile UTL_FILE.FILE_TYPE;
vrecs BOOLEAN := FALSE;
vnodata EXCEPTION;
BEGIN
vFile := UTL_FILE.FOPEN('/devlop, 'norecs.txt', 'w', 32767);
FOR x IN (
SELECT
node_name AS txt
FROM
applsys.fnd_nodes
WHERE
node_name = 'blahblahblah'
LOOP
vrecs := TRUE;
UTL_FILE.PUT_LINE (vFile, x.txt);
END LOOP;
UTL_FILE.FCLOSE(vFile);
IF NOT vrecs THEN
RAISE vnodata;
END IF;
EXCEPTION
WHEN vnodata THEN
*<what can I put here to cause the pl sql block to error???>*
END;
/ -
Pl/sql block reading reading table data from single point in time
I am trying to figure out whether several cursors within a PL/SQL block are executed from within a Single Point In Time, and thus do not see any updates to tables made by other processes or procedures running at the same time.
The reason I am asking is since I have a block of code making some data extraction, with some initial Sanity Checks before the code executes. However, if some other procedure would be modifying the data in between, then the Sanity Check is invalid. So I am basically trying to figure out if there is some read consistency within a PL/SQL, preventing updates from other processes to be seen.
Anyone having an idea?.
BR,
Cenk"Transaction-Level Read Consistency
Oracle also offers the option of enforcing transaction-level read consistency. When a transaction runs in serializable mode, all data accesses reflect the state of the database as of the time the transaction began. *This means that the data seen by all queries within the same transaction is consistent with respect to a single point in time, except that queries made by a serializable transaction do see changes made by the transaction itself*. Transaction-level read consistency produces repeatable reads and does not expose a query to phantoms."
http://www.oracle.com/pls/db102/search?remark=quick_search&word=read+consistency&tab_id=&format=ranked -
PL/SQL block error message
Hi,
I'm still learning PL/SQL. In my application, I created a PL/SQL block which contains an update and an insert statement. When I click Apply Changes, I receive the following error message:
1 error has occurred
ORA-06550: line 24, column 5: PL/SQL: ORA-00933: SQL command not properly ended ORA-06550: line 19, column 2: PL/SQL: SQL Statement ignored
This is my code. I'm not seeing the problem very clearly. Can someone help me out? Thanks.
BEGIN
update
HISA_AGREEMENTS
set
CREATED_BY=V('APP_USER'),
LAST_UPDATED_BY=V('APP_USER'),
APPROVER_SALUTATION=:P7_APPROVER_SALUTATION,
APPROVER_FIRST_NAME=:P7_APPROVER_FIRST_NAME,
APPROVER_MIDDLE_INITIAL=:P7_APPROVER_MIDDLE_INITIAL,
APPROVER_LAST_NAME=:P7_APPROVER_LAST_NAME,
APPROVER_NAME_SUFFIX=:P7_APPROVER_NAME_SUFFIX,
APPROVER_EMAIL_ADDR=:P7_APPROVER_EMAIL_ADDR,
SPONSOR_EMAIL_ADDR=:P7_SPONSOR_EMAIL_ADDR,
APPROVER_TITLE=:P7_APPROVER_TITLE
where
ORG_KEY_LE=:P7_ORG_KEY_LE;
insert into
HISA_AGREEMENT_DOCS
(ORG_DOC_CURR_KEY)
values
(:P7_DOCUMENT)
where
ORG_KEY_LE=:P7_ORG_KEY_LE;
END;Hello,
insert into
HISA_AGREEMENT_DOCS
(ORG_DOC_CURR_KEY)
values
(:P7_DOCUMENT)
where
ORG_KEY_LE=:P7_ORG_KEY_LE;
is wrong. The WHERE clause needs to be omitted...or you need an update.
Greetings,
Roel
http://roelhartman.blogspot.com/
You can reward this reply by marking it as either Helpful or Correct ;-) -
Not able to display javascript alert message from within a pl/sql block
Hello,
Can anyone please help me out with this issue. I wanted to display an javascript alert message from within a pl/sql block for an update button. Below is sample code which i am using. P1_ITEM is my hidden item on the report.
begin
if :P1_ITEM IS NOT NULL then
HTP.p ('<script type="text/javascript">');
HTP.p ('alert(''Please complete the item which is already assigned to you!'');');
HTP.p ('</script>');
end if;
end;
and I have made this code to be executed conditionally when request = Expression1
Expression1: SUBMIT
The thing is I am not able to display an alert message when the update button is clicked.
Can anyone please help me with this one.
Thanks,
Ortonvarad but I also have an update statement within that block for the update button something like this i want to achieve.
begin
if :P1_ITEM IS NULL THEN
update sample_tbl
set col1 =:APP_USER,
col2 = 'Y'
where pk_col = ---;
commit;
HTP.p ('<script type="text/javascript">');
HTP.p ('alert(''Successfully assigned an item!'');');
HTP.p ('</script>');
end if;
if :P1_ITEM IS NOT NULL then
HTP.p ('<script type="text/javascript">');
HTP.p ('alert(''Please complete the item which is already assigned to you!'');');
HTP.p ('</script>');
end if;
end;
thanks,
Orton -
Reading old values in a forms pl/sql block
In a pl/sql block, in a form.
Lets say I want to loop through...
cursor c1 is
select description
from students
where student_id = 1000;
loop
open c1;
fetch c1 into v_description
--step1
update students
set description = new description
where student_id = 1000
--step2
select description into v_old_description where student_id = 1000;
end loop;
In step2 when I am reading the record I am getting the new description which is expected.
My question is how can I get the old description. i-s the value of description which was before step1.
ThanksNo, you perform an update, so the old value is overwritten in the database.
If you really want to use sql, and I don't see why in your example, you can try [flashback query|http://www.oracle.com/technology/deploy/availability/htdocs/Flashback_Overview.htm] . -
Alter database statement in anonymous pl/sql block
Is it possible to include an alter database statement in an anonymous pl/sql block?
When I execute this code to query user_tables for all table names, disable their constraints and drop the table, I got the following error:
***MY CODE
-- DECLARE VARIABLE(S)
DECLARE
v_TABLE_NAME TABLE_NAME.USER_TABLE%TYPE;
-- DECLARE AND DEFINE CURSOR
CURSOR c_GETTABLES is
SELECT TABLE_NAME from USER_TABLES;
BEGIN
OPEN c_GETTABLES;
LOOP
FETCH c_GETTABLES into v_TABLE_NAME;
EXIT when c_GETTABLES%notfound;
ALTER TABLE v_TABLE_NAME DISABLE PRIMARY KEY CASCADE;
DROP TABLE v_TABLE_NAME;
END LOOP;
CLOSE c_GETTABLES;
END;
***RESPONSE FROM SERVER
ALTER TABLE v_TABLE_NAME DISABLE PRIMARY KEY CASCADE;
ERROR at line 15:
ORA-06550: line 15, column 1:
PLS-00103: Encountered the symbol "ALTER" when expecting one of the following:
begin case declare exit for goto if loop mod null pragma
raise return select update while with <an identifier>
<a double-quoted delimited-identifier> <a bind variable> <<
close current delete fetch lock insert open rollback
savepoint set sql execute commit forall merge
<a single-quoted SQL string> pipe
ThanksWhen you want to perform ddl statements in a (anonymous) PL/SQL block, you have to use dynamic SQL because ddl is not possible in pl/sql.
Dynamic sql means that you sort of execute ddl statements in a sql manner. To use dynamic sql, two options exist:
- dbms_sql package : for oracle before 8i. To use this package is not always easy. Read about it carefully first before using.
- Native Dynamic SQL : implemented in 8i and very easy to use. An example would be :
declare
lv_statement varchar2(32676);
begin
lv_statement := 'ALTER TABLE MY_TABLE DISABLE CONSTRAINT MY_TABLE_CK1';
execute immediate lv_statement;
lv_statement := 'ALTER TABLE MY_TABLE ENABLE CONSTRAINT MY_TABLE_CK1';
execute immediate lv_statement;
end;
Good luck.
Edwin van Hattem -
PL/SQL block to populate a table
Hello Gurus,
Need help to write a pl/sql block as per below:
1. Write a PL/SQL block which will populate the RESULTS table as described below. Consider performance implications (specifically where would you commit the queries) as we are dealing with millions of records.
The PL/SQL will:
- insert into the RESULTS table each customer id, and the number of unique products purchased by that customer.
- update the recently_purchased column of the customer table to 'Y' (yes if they have purchased a product in the last 12 months) or 'N' (if they have not purchased a product in the last 12 months).
Listed below are the tables & definitions:
table: CUSTOMER
columns:
customer_id NUMBER,
customer_name VARCHAR2(100),
recently_purchased VARCHAR2(1) -- 'Y' or 'N'
table: CUST_PRODUCTS
columns:
product_id NUMBER,
customer_id NUMBER,
date_purchased DATE
table: RESULTS
columns: customer_id NUMBER, product_count NUMBER
Thanks a lot..Hi Guys,
I've tried this to my best but I feel like something's definately wrong with my update statement.
Please help..
--create customer table
create table customer (
customer_id number(6),
customer_name varchar2(100),
recently_purchased varchar2(1));
-- describe to see if it is created as required
desc customer
--populate customer table with random values
Begin
For i in 1..20
Loop
Insert into customer(customer_id,customer_name,recently_purchased)
values(i, dbms_random.string('U',5),'N');
If mod(i, 100000) = 0 then
Commit;
End if;
End loop;
End;
--create cust_products table
create table cust_products
(product_id number (6),
customer_id number(6),
date_purchased date);
--describe to see if table is created as required
desc cust_products
--populate cust_products with custome_id 1 to 10 and dates
Begin
For i in 1..20
Loop
Insert into cust_products
values(dbms_random.value(555,999),i,add_months('04-Nov-08',i));
If mod(i, 100000) = 0 then
Commit;
End if;
End loop;
End;
select * from cust_products
--update customer table as required
Begin
For i in 1..10
Loop
update customer set recently_purchased = 'Y';
commit;
update customer C set recently_purchased = 'N' where exists (select date_purchased from cust_products P where C.customer_id = P.customer_id );
commit;
End loop;
End;
--Insert into results table
select customer_id,count(product_id)
from cust_products
group by customer_id
Edited by: user497841 on Feb 4, 2010 2:12 PM
Maybe you are looking for
-
Hi Im not sure whether the data will be overwritten for the same key fields in Direct DSO. Please find below my Direct DSO design: Key fields : 0DOC_NUMBER, 0S_ORD_ITEM, 0VBELV, GSS1POSNN Data fields : GSS1STS (Status), GS1JBDATE (Date) The direct DS
-
How do I arrange Pages doc so that page no.s work in duplex print?
Hi Hope one of you bright sparks can help1 I agreed to take on the production/editing of my local village magazine. Created a template, put all the adverts/articles in without too much of a problem, being pretty new to Pages. However when I went to p
-
SSAS using datasource at query time
I have a set of reports that run against the cube. The cube has proactive caching enabled. If the datasource within the SSAS database has invalid credentials, queries against the cube will not run. Note: SSAS is setup to run as network service rat
-
Imovie '09 won't import '08 files HELP!
I imported all my camera contents into iMovie '08 and all worked well. Later, my hard drive crashed so I upgraded to iMovie '09 with the new hard drive. My iMovies files were retrieved from an external hard drive backup. When I try to import the new
-
Does 'For All Entries in itab' work exactly like 'Join' statement?
Hi, I would like to know that if 'For All Entries in itab' work exactly like 'Join' statement? If yes, then when I use 'For All Entries in itab' and a 'Join' statement seperately with the same logical conditions for both, the number of records return