Is there a way to iterate a cursor in a descending order using plsql?
I tried this:
FOR item IN REVERSE items
LOOP
-- do stuff
END LOOP;
but it seems to ignore the reverse key word.
Any suggestions?
It is the SQL clause that determines the order in which the data is traversed, so just apply an appropriate ORDER BY in the query.
DECLARE
cursor c1 is Select * FROM table_1
where (something)
order by (id..whatever you want) DESC; --decrement
v_variable.table%rowtype;
BEGIN
open c1;
fetch c1 into variable; -- will fetch first row...but it will be DESC
close c1;
END;
something like that...
OR
FOR i1 IN c1
LOOP
i1.id...
something...
END LOOP;
OR
FOR i2 IN (Select * FROM table_1
where (something)
order by (id..whatever you want) DESC)
LOOP
--something
END LOOP;
Since you don't have any column to order by, try using order by rownum
Related
Here there is 3 table
1.employee(eid,ename),
2.address(aid,address),
3.employee_add(eid,aid)
employee and address has many to many relation in it.what I need to do is to clean the duplicate from address table without any data loss from employee_add table. thanks in advance! please help
DECLARE
a ADDRESS.AID%TYPE;
b ADDRESS.ADDRESS%TYPE;
c ADDRESS.AID%TYPE;
d ADDRESS.ADDRESS%TYPE;
CURSOR Cur1 IS
SELECT AID,ADDRESS
FROM ADDRESS;
CURSOR Cur2 IS
SELECT AID,ADDRESS
FROM ADDRESS;
BEGIN
OPEN Cur1;
LOOP
FETCH Cur1 INTO a, b;
EXIT WHEN Cur1%NOTFOUND;
OPEN Cur2;
LOOP
FETCH Cur2 into c,d;
IF (b=d) THEN
IF(a!=c) THEN
update employee_add set aid=a where aid=c;
delete from address where aid=c;
END IF;
END IF;
END LOOP;
CLOSE Cur2;
END LOOP;
CLOSE Cur1;
END;
You should be able to do this using the following SQL statements (which you could put inside a PL/SQL procedure if you wanted to), like so:
-- To update the employee_add tables
MERGE INTO employee_add tgt
USING (SELECT ea.rowid rid,
a.aid,
a.address,
MIN(aid) OVER (PARTITION BY address) new_aid
FROM address a
INNER JOIN employee_add ea ON ea.aid = a.aid) src
ON (tgt.rowid = src.rid)
WHEN MATCHED THEN
UPDATE SET tgt.aid = src.new_aid
WHERE tgt.aid != src.new_aid;
-- Delete any rows now longer in the employee_add table
DELETE FROM address
WHERE aid NOT IN (SELECT aid FROM employee_add);
-- If you need to deduplicate the employee_add table, this should do the trick:
DELETE FROM employee_add ea1
WHERE ROWID > (SELECT MIN(ROWID)
FROM employee_add ea2
WHERE ea1.eid = ea2.eid
AND ea1.aid = ea2.aid;
In general, explicit cursor is slower than implict cursor.
You can try to convert the
OPEN ...
LOOP
FETCH ...
EXIT WHEN ...
...
...
END LOOP;
into
FOR ... LOOP
...
END LOOP;
else, it would help if you provide some DDLs & DMLs (together with PK, indexes and constraints).
My table has a defined column id.
Though the same query runs fin e independently,but when I try to declare it in a cursor, it shows invalid column.
declare
type PA_1 is record (PI number);
calc number;
row_container PA_1;
begin
for row_container in
(
select distict t1.pi , t2.id
from table1 t1, table2 t2
where t1.Pi=t2.pi
);
Loop
select calculation to calc
from table1 t1
where t1.pi=row_container.pi and t2.id=row_container.id;
end loop;
commit;
end;
the inner query runs fine otherwise. Please help
Several syntax errors:
First of all, you should remove the declaration for row_container. for row_container in () makes this inplicitely (and your declaration with one column doesn't even match your query with two columns).
distict should be distinct.
Then remove the semicolon before the Loop keyword. It doesn't belong there.
Then select calculation to calc should be select calculation into calc.
Inside the loop you select from table1 (which you call t1 again), but your where clause contains t2.id, while there is no t2 in that query.
And then: What is this routine supposed to do? It selects some value into the variable calc, but doesn't use it. So once it runs, it just doesn't do anything.
This is sql block i'm using in Oracle,
Now I need to do the same way in Teradata, Is possible? I want the syntax FOR UPDATE CURSOR in Teradata!
Can you please guide me?
declare
cursor c1 is select * from Employees FOR UPDATE;
a number :=0 ;
begin
for x in c1 loop
a := a +1 ;
update employees set salary = a where current of c1;
end loop;
end;
Updateable cursors are allowed in ANSI-mode sessions only.
The syntax is quite similar:
declare c1 cursor for
select * from Employees FOR UPDATE;
a number :=0 ;
begin
for x in c1 loop
a := a +1 ;
update employees set salary = a where current of c1;
end loop;
end;
But cursors perform really bad in a parallel DBMS like Teradata as they're processed serially, one row after the other.
In almost every case cursors on data can be rewritten set-based (e.g. your example is a simple ROW_NUMBER) and then they perform several orders of magnitude faster.
Maybe you could use this instead?
UPDATE employees
FROM (
SELECT csum(1,1) new_salary, emp_id
FROM employees
) src
set salary=src.new_salary
where employees.emp_id=src.emp_id;
Suppose In my procedure, there are two cursors and I have a requirement of writing from both the cursors, 1st line from 1st cursor and 2nd line from 2nd cursor and so on..
How do i achieve it??? I know how to fetch from single curs
or.
Or there is some other way.
Thanks in Advance,
Nitika
You could use two for loop statements, like this:
CREATE OR REPLACE procedure aProc(filter IN number) IS
cursor c1 is select something, something_else from myTable where something = filter;
cursor c2 is select something2, something_else2 from myTable2;
begin
for alias1 in c1 loop
for alias2 in c2 loop
if(alias1.something = 1) then
insert into myTable3 (value1,value2,value3)
values (alias1.something_else,
alias2.something2,
alias2.something_else2);
end if;
end loop;
end loop;
end;
The for loop statement will close the open cursors when no more data is found.
I am new to PL/SQL, and am working on cursor today and got a scenario where I need to get the duplicate transaction type based on the date+amount+cust_id+txn_tpye. Once I get the duplicates I have to use another cursor or just normal loop using the select columns values (date+amount+cust_id+txn_tpye) as a where clause.
Before that I'm just trying to print them if I am getting a value or not, when I tried to print a mydate value getting error. Requesting help from you folks.
SET SERVEROUTPUT ON
declare
CURSOR dup_check
IS
SELECT cust_id,amount,trunc(mydate),transaction_type,COUNT(1)
FROM table_X WHERE trunc(mydate)>='10-OCT-2015'
GROUP BY cust_id,amount,trunc(mydate),transaction_type
HAVING COUNT(1)>1 ;
BEGIN
FOR UP_REC IN dup_check
LOOP
DBMS_OUTPUT.put_line(UP_REC.cust_id||' '||UP_REC.amount||UP_REC.trnasaction_type||**trunc(mydate))**;
END LOOP;
END;
**PLS-00302: component 'mydate' must be declared**
add alias for trunc(mydate) field as below and put the UP_REC.mydate in your dbms_output
SET SERVEROUTPUT ON
declare
CURSOR dup_check
IS
SELECT cust_id,
amount,
trunc(mydate) mydate, /* add an alias here */
transaction_type,
COUNT(1)
FROM table_X WHERE trunc(mydate) >= '10-OCT-2015'
GROUP BY cust_id,amount,trunc(mydate),transaction_type HAVING COUNT(1)>1 ;
BEGIN
FOR UP_REC IN dup_check
LOOP
DBMS_OUTPUT.put_line(UP_REC.cust_id||' '||UP_REC.amount||UP_REC.trnasaction_type||UP_REC.mydate));
END LOOP;
END;