PL/SQL Calling a function to a procedure - plsql

Previously,I asked about creating a function that returns total amount of salaries from a parameter city.
I chose Dallas for instance.Tables are EMP and DEPT:
You can find them below
https://livesql.oracle.com/apex/livesql/file/content_O5AEB2HE08PYEPTGCFLZU9YCV.html
Mistakenly I wrote in my language instead of english at the end of it but I corrected it.
Now I need to create a procedure which lists ascending the employees and their salaries from another parameter city.After listing them I need to call the function for the second city.Problem is I get an error for the 'loop' from the procedure and i got no idea why.
set serveroutput on;
create or replace function show_sal (local dept.loc%type) return number as
vval number;
begin
select sum(emp.sal)
into vval
from emp inner join dept on dept.deptno = emp.deptno
where upper(dept.loc) = upper(local);
return vval;
end;
/
begin
dbms_output.put_line('Total sum of salaries from DALLAS = ' || show_sal('DALLAS'));
end;
/
-------------------------------------------------------------------------------------------------
CREATE OR REPLACE PROCEDURE show_employees(v_loc dept.loc%TYPE) AS
CURSOR c IS
SELECT ename,sal
FROM emp INNER JOIN dept ON emp.deptno = dept.deptno
WHERE UPPER(loc)=UPPER(v_loc)
ORDER BY ename ASC;
v_name VARCHAR2;
v_salaries emp.sal%TYPE;
BEGIN
OPEN c
LOOP
FETCH c INTO v_name,v_salaries;
EXIT WHEN c%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_name||' '|| v_salaries);
END LOOP;
CLOSE c;
END;
/
EXECUTE show_employees('CHICAGO');
BEGIN
show_sal('CHICAGO');
END;
/

You simply forgot the semicolon after OPEN c.
And here is how to do the same with an implicit cursor, which is much easier to deal with in my opinion:
CREATE OR REPLACE PROCEDURE show_employees(v_loc dept.loc%TYPE) AS
BEGIN
FOR rec IN
(
SELECT ename, sal
FROM emp
WHERE deptno IN (SELECT deptno FROM dept WHERE UPPER(loc) = UPPER(v_loc))
ORDER BY ename
) LOOP
DBMS_OUTPUT.PUT_LINE(rec.ename || ' ' || rec.sal);
END LOOP;
END show_employees;

Errors i get:
Function SHOW_SAL compiled
Total sum of salaries from DALLAS = 10875
PL/SQL procedure successfully completed.
Procedure SHOW_EMPLOYEES compiled
LINE/COL ERROR
9/9 PLS-00215: String length constraints must be in range (1 .. 32767)
Errors: check compiler log
Error starting at line : 40 in command -
BEGIN show_employees('CHICAGO'); END;
Error report -
ORA-06550: line 1, column 61:
PLS-00905: object HR.SHOW_EMPLOYEES is invalid
ORA-06550: line 1, column 61:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
Error starting at line : 42 in command -
BEGIN
show_sal('CHICAGO');
END;
Error report -
ORA-06550: line 2, column 1:
PLS-00221: 'SHOW_SAL' is not a procedure or is undefined
ORA-06550: line 2, column 1:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:

set serveroutput on;
create or replace function show_sal (local dept.loc%type) return number as
vval number;
begin
select sum(emp.sal)
into vval
from emp inner join dept on dept.deptno = emp.deptno
where upper(dept.loc) = upper(local);
return vval;
end;
/
begin
dbms_output.put_line('Total sum of salaries from DALLAS = ' || show_sal('DALLAS'));
end;
/
-------------------------------------------------------------------------------------------------
CREATE OR REPLACE PROCEDURE show_employees(v_loc dept.loc%TYPE) AS
CURSOR C is SELECT ename,sal
FROM emp,dept
WHERE emp.deptno=dept.deptno AND UPPER(loc)=UPPER(v_loc)
ORDER BY ename ASC;
v_nume emp.ename%TYPE;
v_salariu emp.sal%TYPE;
v_tot emp.sal%TYPE;
BEGIN
v_tot:=show_sal('CHICAGO');
dbms_output.put_line('nume salar total: '||v_tot);
OPEN C;
LOOP
FETCH C INTO v_nume,v_salariu;
EXIT WHEN C%NOTFOUND;
dbms_output.put_line(v_nume||' '||v_salariu);
END LOOP;
CLOSE C;
END;
/
EXECUTE show_employees('CHICAGO');

Related

PL/SQL: I get expression 'I' cannot be used as an assignment target

My code:
create table info(str varchar2(30));
declare
cursor c(job emp_ast.job_id%type, dep emp_ast.department_id%type) is select employee_id
from emp_ast
where job_id=job and department_id=dep;
type t_job is table of emp_ast.job_id%type;
t t_job:=t_job();
emp emp_ast.employee_id%type;
i number(3);
begin
select job_id
bulk collect into t
from emp_ast;
for i in 10..270 loop
for j in 1..t.count loop
open c(i, t(j));
loop
fetch c into emp;
insert into info
values (i||' '||t(j)||' '||emp);
exit when c%notfound;
end loop;
i:=i+10;
end loop;
end loop;
end;
/
I get "expression 'I' cannot be used as an assignment target", reffering to the line where I increment i by 10. I am trying to save the department_id, employee_id and job_id as a string in a table for each department and each job.
At the point where you get that message, i refers to the loop control variable i defined in the line for i in 10..270 loop, not the int(3) variable defined earlier. In PL/SQL a loop definition defines a variable which is only accessible inside the loop, and which you cannot alter. I suggest you change the name of one or the other to make them unique.
EDIT
PL/SQL doesn't provide a way to step by more than 1 in a computed FOR loop. Instead, you will need to compute the desired department number value within the loop:
DECLARE
CURSOR c(job EMP_AST.JOB_ID%TYPE,
dep EMP_AST.DEPARTMENT_ID%TYPE)
IS SELECT EMPLOYEE_ID
FROM EMP_AST
WHERE JOB_ID = job AND
DEPARTMENT_ID = dep;
TYPE t_job IS TABLE OF EMP_AST.JOB_ID%TYPE;
t t_job := t_job();
emp EMP_AST.EMPLOYEE_ID%TYPE;
nDepartment NUMBER;
BEGIN
SELECT job_id
BULK COLLECT INTO t
FROM EMP_AST;
FOR i IN 1..27 LOOP
nDepartment := i * 10;
FOR j IN 1..t.COUNT LOOP
OPEN c(t(j), nDepartment);
LOOP
FETCH c INTO emp;
INSERT INTO info
VALUES (nDepartment || ' ' || t(j) || ' ' || emp);
EXIT WHEN c%notfound;
END LOOP; -- cursor c
CLOSE c;
END LOOP; -- j
END LOOP; -- i
END;
/
Note that in the code above the nDepartment value is computed within the i loop, which now increments from 1 to 27 instead of going from 10 to 270.

using nested table as in Parameter to a Procedure

I have a table T1 and I want to insert multiple rows at a time through a procedure using collection. I have written the code but when I'm trying to execute it throws an error. Please advise.
create table t1 ( id number , name varchar2(10));
/
create or replace PACKAGE PKG1 AS
TYPE TAB_LIST IS TABLE OF T1%ROWTYPE;
PROCEDURE PROC1 (p_val IN TAB_LIST);
END PKG1;
/
create or replace PACKAGE BODY PKG1 AS
PROCEDURE PROC1 (P_VAL IN TAB_LIST
)
IS
BEGIN
FOR i IN p_val.FIRST..p_val.LAST
LOOP
insert INTO T1
(
id, name
)
VALUES
(
p_val(i).id,
p_val(i).name
);
END LOOP;
END;
END;
error after executing
DECLARE
p_val PKG1.TAB_LIST;
BEGIN
p_val := PKG1.TAB_LIST(123,'XYZ');
END;
Error report -
ORA-06550: line 5, column 11:
PLS-00306: wrong number or types of arguments in call to 'TAB_LIST'
ORA-06550: line 5, column 11:
PLS-00306: wrong number or types of arguments in call to 'TAB_LIST'
ORA-06550: line 5, column 2:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
DECLARE
P_VAL PKG1.TAB_LIST := PKG1.TAB_LIST();
BEGIN
P_VAL.extend;
P_VAL(1).id := 123;
P_VAL(1).name := 'XYZ';
PKG1.PROC1( P_VAL );
END;
example for multiple records:
DECLARE
P_VAL PKG1.TAB_LIST := PKG1.TAB_LIST();
BEGIN
for i in 1 .. 10
loop
P_VAL.extend;
P_VAL(P_VAL.LAST).id := i;
P_VAL(P_VAL.LAST).name := 'XYZ' || i;
end loop;
PKG1.PROC1( P_VAL );
END;
#hekko": its not a string .sorry about formatting . The multiple values (n) can be passed from application like this and all should be inserted into table at once.
123 'XYZ'
456 'DFK'
866 'HKK'
#Kaushik :it is not a string but formatting issue.. the question remains the same "I have a table T1 and I want to insert multiple rows at a time through a procedure using collection.

insert clob datatypefrom sql server

I have the below code to insert clob datatype from SQL server to Oracle Database using DBlink.
I m currently facing the error :
ORA-06502: PL/SQL: numeric or value error: invalid LOB locator specified: ORA-22275
ORA-06512: at "SYS.DBMS_LOB", line 639. Can you please help me what could be the issue with the code?
declare
v_REGION_CODE CLOB ;
l_clob CLOB;
c integer;
nr integer;
BEGIN
DBMS_LOB.CREATETEMPORARY(l_clob,true);
EXECUTE IMMEDIATE 'TRUNCATE TABLE SVQ_DI_XLS_COUNTRY_POP_DETAILS';
c := DBMS_HS_PASSTHROUGH.OPEN_CURSOR#PPRLEG;
DBMS_HS_PASSTHROUGH.PARSE#PPRLEG(c,' SELECT "REGION CODE" FROM TBL_SVQ_DI_XLS_COUNTRY_POP_DETAILS');
LOOP
nr := DBMS_HS_PASSTHROUGH.FETCH_ROW#PPRLEG(c);
EXIT
WHEN nr = 0;
DBMS_HS_PASSTHROUGH.GET_VALUE#PPRLEG(c, 1 , v_REGION_CODE ) ;
FOR i IN 1..10
LOOP
INSERT INTO SVQ_DI_XLS_COUNTRY_POP_DETAILS (REGION_CODE) VALUES (empty_clob()) --Insert an "empty clob" (not insert null)
RETURNING REGION_CODE INTO l_clob;
FOR i IN 1..100
LOOP
dbms_lob.append(l_clob, v_REGION_CODE);
--dbms_lob.append(l_clob, 'string chunk to be inserted (maximum 4000 characters at a time)');
END LOOP;
END LOOP;`enter code here`
END LOOP;
DBMS_HS_PASSTHROUGH.CLOSE_CURSOR#PPRLEG(c);
COMMIT;
END;

Oracle PL/SQL SUBSTR error

i need to convert a varchar to an array using pl/sql, but when i use the SUBSTR function, i get this error:
Error report -
ORA-06550: line 12, column 3:
PLS-00330: invalid use of type name or subtype name
ORA-06550: line 12, column 3:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
this is my code:
SET SERVEROUTPUT ON;
DECLARE
v_string varchar2(20) := 'hello';
type array_string is varray(5) of varchar2(10);
v_length number;
cnt number;
v_char char(1);
BEGIN
v_length := length(v_string);
while (cnt < v_length)
loop
v_char := SUBSTR(v_string, cnt, 1);
array_string(cnt) := v_char;
cnt := cnt + 1;
end loop;
END;
when i (partially) type 'SUBSTR' it autocompletes to SUBSTR(SQLERRM, 1, 64) so it should know the command, right?
what am i doing wrong? im pretty new at pl/sql
regards,
You must initialize variable cnt before using it in substr.
You must use variable name instead of type name in array_string(cnt).
You must extend your varray before writing new value to it.
In oracle environment, the starting index for varrays is always 1.
Your cnt is starting from 0. So the during the first time execution of the loop, the
a_string(cnt) := v_char;
cnt is 0.
Initialize cnt as 1, and run the loop for
while (cnt < 5)
This will remove the error you are getting

PLS-00103 when running script in APEX

I'm trying to run the following PLSQL script in APEX:
DECLARE
total NUMBER;
BEGIN
SELECT COUNT(*)
INTO total
FROM one_table;
FOR i IN 0:100 --This is line 8
LOOP
INSERT INTO other_table(id, column_a) SELECT id + i * total, column_a FROM one_table;
END LOOP;
COMMIT;
END;
And I get this error:
ORA-06550: line 8, column 15: PLS-00103: Encountered the symbol "" when expecting one of the following: * & - + / at mod remainder rem .. <an exponent (**)> || multiset The symbol ".." was substituted for "" to continue.'
I don't think this is legal syntax:
FOR i IN 0:100
I think you mean:
FOR i IN 0..100

Resources