why incremented value is coming as null after end of loop? - oracle

V_TOTAL_SIZE_MB values are coming within the loop but when I try to print V_TOTAL_SIZE_GB is coming as null after loop or inside the loop.
DECLARE
V_TOTAL_SIZE_MB NUMBER;
V_TOTAL_SIZE_GB NUMBER := 0.0;
CURSOR c1
IS
select NODE_ID from dept where id=12;
BEGIN
FOR c1_rec IN c1
LOOP
SELECT SUM(round(u.size/1024/1024,2))
INTO V_TOTAL_SIZE_MB
from child
WHERE =c1_rec.NODE_ID;
V_TOTAL_SIZE_GB := V_TOTAL_SIZE_GB+V_TOTAL_SIZE_MB;
dbms_output.put_line(':::V_TOTAL_SIZE_MB:'|| V_TOTAL_SIZE_MB);
END LOOP;
dbms_output.put_line(':::TOTAL_SIZE_GB:'|| V_TOTAL_SIZE_GB/1024);
END;

Related

Insert data into nested table plsql

Well, I want to insert data from a table into a nested table.
SET SERVEROUTPUT ON;
DECLARE
TYPE employee_type IS TABLE OF employees.salary%TYPE;
emps employee_type;
i NUMBER(5) := 100;
sal employees.salary%TYPE;
BEGIN
LOOP
SELECT salary INTO sal FROM employees WHERE employees.employee_id = i;
emps := employee_type(sal);
i := i + 1;
EXIT WHEN i > 110;
END LOOP;
SYS.DBMS_OUTPUT.PUT_LINE(emps.count);
This is my code but when I do SYS.DBMS_OUTPUT.PUT_LINE(emps.count); I only get 1 but it should be 10 actually
This:
emps := employee_type(sal);
initializes the collection with a single element containing the salary. Every time you do this, you erase the existing collection and replace it with a new one consisting of one element only again.
Instead, initialize the collection once and then extend it element by element:
DECLARE
TYPE employee_type IS TABLE OF employees.salary%TYPE;
emps employee_type := employee_type(); -- initializing the array right away
i NUMBER(5) := 100;
sal employees.salary%TYPE;
BEGIN
LOOP
SELECT salary INTO sal FROM employees WHERE employees.employee_id = i;
emps.EXTEND(1); -- add one element
emps(emps.COUNT) := sal; -- fill that element
i := i + 1;
EXIT WHEN i > 110;
END LOOP;
SYS.DBMS_OUTPUT.PUT_LINE(emps.count);
END;
It is much easier though to bulk collect the values into the array (which also implicitly initialized the array).
DECLARE
TYPE employee_type IS TABLE OF employees.salary%TYPE;
emps employee_type;
i NUMBER(5) := 100;
BEGIN
SELECT salary BULK COLLECT INTO emps
FROM employees
WHERE employee_id BETWEEN i AND 110;
SYS.DBMS_OUTPUT.PUT_LINE(emps.count);
END;

Getting ORA-06532: Subscript outside of limit

I have created varray collection type inorder to get a serv_item_id column value from serv_item table. But while executing im getting subsript outside of limit error.
declare
type t1 is varray(1000) of serv_item%rowtype;
v_t1 t1:=t1();
n number :=0;
cursor c1 is select * from serv_item;
begin
open c1;
loop
v_t1.extend();
fetch c1 into v_t1(n);
exit when c1%notfound;
n:=n+1;
end loop;
close c1;
for i in 0..v_t1.count
loop
dbms_output.put_line('The serv item'||v_t1(i).serv_item_id);
end loop;
end;
/
varray indexing begins at 1, not 0.

PL/SQL Nested Loops with cursors

I am working with Oracle PL/SQL. There are two cursors, namely c1 and c2.
v_temp VARCHAR(50);
For s1 IN c1
LOOP
--do something
FOR s2 IN c2
LOOP
--do something
v_temp := s1.s2.xxx; --PLS-00302: component 's2' must be declared
END LOOP;
END LOOP;
s2.xxx gives a column name, and with that column name I hope to assign the value of that column from s1 to v_temp.
For example:
In the first iteration, s2.xxx is 'column1',
I would like to assign s1.column1 to v_temp. In the second iteration, s2.xxx is 'column2', I would then like to assign s1.column2 to v_temp.
I got the error:
Error(191,48): PLS-00302: component 's2' must be declared
while trying to compile. I know that s1.s2.xxx is not valid, but is there another way of writing it that can make it work?
You need to fetch from a REF CURSOR and dynamically append the column_name to the select statement while opening the cursor. Here I am fetching all the column names from USER_TAB_COLUMNS for table EMPLOYEES and assigning their corresponding values to v_temp.
SET SERVEROUTPUT ON;
DECLARE
v_temp VARCHAR(50);
query1 VARCHAR2(1000);
c1 SYS_REFCURSOR;
CURSOR c2
IS
SELECT COLUMN_NAME xxx FROM USER_TAB_COLUMNS WHERE TABLE_NAME = 'EMPLOYEES';
BEGIN
FOR s2 IN c2
LOOP
--do something
query1 := 'SELECT ' ||s2.xxx||' FROM EMPLOYEES';
OPEN c1 FOR query1 ;
LOOP
FETCH c1 INTO v_temp;
DBMS_OUTPUT.PUT_LINE('COLUMN:'||s2.xxx||', VALUE:'|| v_temp);
EXIT
WHEN c1%NOTFOUND;
END LOOP;
CLOSE c1;
END LOOP;
END;
/
Since lengths of all the columns of Employees are < 50 , it is working Fine.The conversion happens implicitly for NUMBER and DATE data types.
Here is a sample Output.
COLUMN:EMPLOYEE_ID, VALUE:100
COLUMN:EMPLOYEE_ID, VALUE:101
COLUMN:EMPLOYEE_ID, VALUE:102
COLUMN:FIRST_NAME, VALUE:Eleni
COLUMN:FIRST_NAME, VALUE:Eleni
COLUMN:LAST_NAME, VALUE:Whalen
COLUMN:LAST_NAME, VALUE:Fay
COLUMN:HIRE_DATE, VALUE:17-06-03
COLUMN:HIRE_DATE, VALUE:21-09-05
I think you need smth like that:
declare
v_temp VARCHAR(50);
v_temp_1 VARCHAR(50);
cursor c2(p VARCHAR) is
SELECT *
FROM tbl
WHERE tbl.column = p;
begin
For s1 IN c1
LOOP
--do something
v_temp_1 := s1.xxx;
FOR s2 IN c2(v_temp_1)
LOOP
--do something
v_temp := s1.xxx;
END LOOP;
END LOOP;
end;

(Oracle) How to get sum value inside loop?

I need value of sum inside loop.
DECLARE
VAR_PCT NUMBER;
CURSOR C1 IS
SELECT A, B FROM TBL;
BEGIN
FOR REC1 IN C1
LOOP
--This where i need the value of sum(rec1.b) to calculate VAR_PCT:=(REC1.B/SUM(REC1.B))*100
DBMS_OUTPUT.PUT_LINE(REC1.A ||'|'|| REC1.B ||'|'||VAR_PCT)
END LOOP;
END;
So, I basically need to figure out how to get the sum of B.
EDIT:
I forgot that I have one more variable that accumulate before the sum
*FOR REC1 IN C1
LOOP*
VAR_X := VAR_X+REC1.B
*--This where i need the value of sum(rec1.b) to calculate VAR_PCT:=(REC1.B/SUM(REC1.B))*100
DBMS_OUTPUT.PUT_LINE(REC1.A ||'|'|| REC1.B ||'|'||VAR_PCT)
END LOOP;*
And the VAR_PCT is value for (VAR_X/SUM(REC1.B))*100
That's why I need calculate it inside the loop.
You can use window function sum(col) over () to find the overall total in the cursor definition itself. This is usually more performant then doing thing procedurally in a loop.
DECLARE
CURSOR C1 IS
SELECT A, B, 100 * b / sum(b) over () VAR_PCT FROM TBL;
BEGIN
FOR REC1 IN C1
LOOP
DBMS_OUTPUT.PUT_LINE(REC1.A ||'|'|| REC1.B ||'|'||REC1.VAR_PCT)
END LOOP;
END;
If the sum is for each A, then use partition by:
DECLARE
CURSOR C1 IS
SELECT A, B, 100 * b / sum(b) over (partition by A) VAR_PCT FROM TBL;
BEGIN
FOR REC1 IN C1
LOOP
DBMS_OUTPUT.PUT_LINE(REC1.A ||'|'|| REC1.B ||'|'||REC1.VAR_PCT)
END LOOP;
END;

How to Specify Array variable in plsql

Can any one please help me, how to assign result of select query to a array variable since result can be an array of values.
There are a couple of different approaches you could take to get data into your array. The first would be a simple loop, as in the following:
DECLARE
TYPE NUMBER_ARRAY IS VARRAY(100) OF NUMBER;
arrNums NUMBER_ARRAY;
i NUMBER := 1;
BEGIN
arrNums := NUMBER_ARRAY();
FOR aRow IN (SELECT NUMBER_FIELD
FROM A_TABLE
WHERE ROWNUM <= 100)
LOOP
arrNums.EXTEND;
arrNums(i) := aRow.SEQUENCE_NO;
i := i + 1;
END LOOP;
end;
Another, as suggested by #Rene, would be to use BULK COLLECT, as follows:
DECLARE
TYPE NUMBER_ARRAY IS VARRAY(100) OF NUMBER;
arrNums NUMBER_ARRAY;
BEGIN
arrNums := NUMBER_ARRAY();
arrNums.EXTEND(100);
SELECT NUMBER_FIELD
BULK COLLECT INTO arrNums
FROM A_TABLE
WHERE ROWNUM <= 100;
end;
Share and enjoy.

Resources