How to avoid this in PLSQL - oracle

I'm trying to create a function that looks like this
CREATE OR REPLACE FUNCTION get_sal
(dep_id IN departments.department_id%TYPE)
RETURN NUMBER IS
v_sal employees.salary%TYPE;
BEGIN
SELECT AVG(salary) INTO v_sal FROM Employees
WHERE department_id = dep_id;
RETURN v_sal;
END;
And I get an error that says
Error starting at line : 5 in command -
BEGIN
SELECT AVG(salary) INTO v_sal FROM Employees
WHERE department_id = dep_id;
RETURN v_sal;
END;
Error report -
ORA-06550: line 3, column 27:
PL/SQL: ORA-00904: "DEP_ID": invalid identifier
ORA-06550: line 2, column 5:
PL/SQL: SQL Statement ignored
ORA-06550: line 4, column 5:
PLS-00372: In a procedure, RETURN statement cannot contain an expression
ORA-06550: line 4, column 5:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
I got an example function from Oracle to see if it works but the same error appears.

There's nothing wrong with the function:
SQL> CREATE OR REPLACE FUNCTION get_sal (dep_id IN departments.department_id%TYPE)
2 RETURN NUMBER
3 IS
4 v_sal employees.salary%TYPE;
5 BEGIN
6 SELECT AVG (salary)
7 INTO v_sal
8 FROM Employees
9 WHERE department_id = dep_id;
10
11 RETURN v_sal;
12 END;
13 /
Function created.
SQL> select get_sal(10) from dual;
GET_SAL(10)
-----------
SQL>
as long as schema you're connected to contains DEPARTMENTS and EMPLOYEES tables with columns mentioned in that code. If you do not, then yes - expect errors.

As it seems you are using Sql Developer 20.4.0 as your SQL client, i guess the problem comes from the way you're compiling your SQL statement within this SQL client.
With SQL Developer, there is two ways to compile a SQL statement/execute a query. Selecting it in the editor and then click the green play button on the left as shown in the image below. The second way is to have only your statements in the editor and use the execute script button which is the second button to the right of the green play button. This one will execute all the statements in the editor.
I guess your error come from the use of the green play button while your cursor in the editor is on the statement but the statement is not fully selected or partially selected.
You can make SQL Developer complies with the behavior of Toad or have a custom behavior in this way in the SQL Developer options.

Related

plsql using in datagrip ide

When I am running PL/SQL scripts in Datagrip I am getting task compiled but I cannot see the output how to get an output in datagrip,
and when I am running dynamic block it's not taking input value in datagrip.
declare
v1 emp.empno%type := '&empno';
v2 emp.ename%type;
begin
select empno,ename into v1,v2 from emp where empno = v1;
DBMS_OUTPUT.PUT_LINE(v1 || ' ' || v2);
end;
it shows this error
ORA-06502: PL/SQL: numeric or value error: character to number conversion error
Does anyone have any solution?
Enable DBMS_OUTPUT button is placed on the right toolbar of the Services window
I don't use DataGrip.
Looks like you should enable dbms_output. How? Try with [Ctrl + F8] (as a keyboard shortcut), or push the appropriate button (tooltip says "Enable SYS.DBMS_OUTPUT").
As of the second part of your question, documentation says
Generally, only the question mark ? is treated as a parameter in SQL statements, which means that you might need to do this:
v1 emp.empno%type := ?;
Because, code you posted works OK in e.g. SQL Developer or SQL*Plus:
Enabling DBMS_OUTPUT:
SQL> set serveroutput on
Code execution:
SQL> declare
2 v1 emp.empno%type := '&empno';
3 v2 emp.ename%type;
4 begin
5 select empno,ename into v1,v2 from emp where empno = v1;
6 DBMS_OUTPUT.PUT_LINE(v1 || ' ' || v2);
7 end;
8 /
Enter value for empno: 7369
7369 SMITH --> this is the result
PL/SQL procedure successfully completed.
SQL>
Finally, ORA-06502: it happens when you pass something that isn't a number (while number is expected); for example, I'll pass ABC:
SQL> /
Enter value for empno: ABC
declare
*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: character to number conversion error
ORA-06512: at line 2
SQL>
See? The same error you got. Maybe it all has to do something with improper usage of a substitution variable, i.e. '&empno' vs. ?

I don't understand what is the problem in my store procedure

Create or replace PROCEDURE SSp_EmpHoursInfo
(p_EHrsInfo OUT SYS_REFCURSOR)
AS
BEGIN
OPEN p_EHrsInfo FOR
Select
a.personid, a.first_name, a.last_name,c.hoursworked,d.carecentername, c.break
from person a
join employee b on a.personid = b.empersonid
join employee_assigned_care_center c on b.empersonid = c.empersonid
join care_center d on c.empersonid = d.carecenterid
where hoursworked> 10;
END SSp_EmpHoursInfo;
Everytime I am trying to call the store procedure it is giving me this error msg:
Error starting at line : 225 in command -
BEGIN SSp_EmpHoursInfo (hoursworked> 10); END;
Error report -
ORA-06550: line 1, column 3:
PLS-00201: identifier 'HOURSWORKED' must be declared
ORA-06550: line 1, column 52:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
The problem is very obvious.
BEGIN SSp_EmpHoursInfo (hoursworked> 10); END; is not the proper way of calling it.
The procedure parameter must be the sys_refcursor.
You must use:
DECLARE
OUTPUT_CUR SYS_REFCURSOR;
BEGIN
SSp_EmpHoursInfo (OUTPUT_CUR );
-- USE CURSOR ACCORDINGLY
END;
/

Apex button and procedure

Im trying to create button in Apex which execute given procedure. As input values I gave two date fields called Poczatek and Koniec. The button should execute this procedure on submit. It perfectly works in Oracle, but throw a lot of errors in Apex.
set serveroutput on
create or replace procedure KORELACJA(:Poczatek, :Koniec)
IS
miasto VARCHAR(25);
korelacja NUMBER;
cursor c1 is
SELECT TEMP.nazwa, corr(TEMP.temperatura, WILGOTNOSC.wilg)
FROM TEMP INNER JOIN WILGOTNOSC
on TEMP.nazwa = WILGOTNOSC.nazwa
and TEMP.data = WILGOTNOSC.data
WHERE TEMP.data between to_date(:Poczatek, 'YYYY-MM-DD') and to_date(:Koniec, 'YYYY-MM-DD')
GROUP BY TEMP.nazwa;
BEGIN
DBMS_OUTPUT.put_line(RPAD('Miasto',10)||RPAD('Korelacja',10));
open c1;
FOR i IN 1..6
LOOP
commit;
fetch c1 into miasto, korelacja;
DBMS_OUTPUT.put_line(RPAD(miasto,10)||RPAD(korelacja,10));
END LOOP;
close c1;
END KORELACJA;
/
Errors look like this:
1 error has occurred
ORA-06550: line 2, column 5: PL/SQL: ORA-00922: missing or invalid option
ORA-06550: line 2, column 1: PL/SQL: SQL Statement ignored ORA-06550: line 6,
column 11: PLS-00103: Encountered the symbol "NUMBER" when expecting one of the
following: := . ( # % ; ORA-06550: line 9, column 18: PLS-00103: Encountered the symbol "JOIN" when
expecting one of the following: , ; for group having intersect minus order start
union where connect
Anyone knows the solution?
I'd suggest you to leave the procedure in the database; call it from Apex.
As you said that it works OK, I'm not going to examine the code. Just modify the first line:
create or replace procedure KORELACJA(par_Poczatek in date,
par_Koniec in date)
is ...
Then, in Apex process, call the procedure as
korelacja(:p1_poczatek, :p2_koniec);
Note that you might need to apply TO_DATE function to those items, using appropriate format mask, such as
korelacja(to_date(:p1_poczatek, 'dd.mm.yyyy',
to_date(:p1_koniec , 'dd.mm.yyyy');
If you insist on keeping the procedure in Apex' process (I wouldn't recommend it), the you don't need CREATE PROCEDURE but an anonymous PL/SQL block. It won't accept any parameters - use Apex items directly.
declare
miasto VARCHAR(25);
korelacja NUMBER;
cursor ...
WHERE TEMP.data between to_date(:p1_Poczatek, 'YYYY-MM-DD') ...
begin
...
end;

how to take value in composite record type in plsql

ERROR at line 4: ORA-06550: line 4, column 5: PLS-00320: the
declaration of the type of this expression is incomplete or malformed
ORA-06550: line 2, column 1: PL/SQL: Item ignored ORA-06550: line 4,
column 1: PLS-00320: the declaration of the type of this expression is
incomplete or malformed ORA-06550: line 10, column 10: PL/SQL:
ORA-00904: : invalid identifier ORA-06550: line 9, column 1: PL/SQL:
SQL Statement ignored
declare
type emp_detp_record is record
(
emp emp%rowtype,
dept dept%rowtype
);
emp_dept emp_detp_record;
begin
select * into
emp_dept
from emp,dept
where emp.deptno =dept.deptno
and empno =7839;
end;
/
You can use a CURSOR and anchor the record to the cursor's ROWTYPE:
declare
cursor emp_dept_cur is
select *
from emp
join dept on emp.deptno = dept.deptno;
emp_dept_rec emp_dept_cur%rowtype;
begin
select * into
emp_dept_rec
from emp
join dept on emp.deptno =dept.deptno
where empno = 7839;
-- dbms_output.put_line(emp_dept_rec.deptno); -- raises PLS-00302: component 'deptno' must be declared
end;
Some notes:
please don't use the old Oracle syntax for JOINs (multiple tables in the FROM clause). Use ANSI JOINs instead
this will cause problems with duplicate column names. In your example, you have two columns named deptno - one from emp and one from dept. This will raise an error as soon as you try to access it (see commented line in my code)
I use collections to handle such scenarios. Hope this might help you.
declare
cursor emp_dept_cur is
select emp.empno,dept.deptno
from emp,dept
where emp.deptno =dept.deptno
and empno =7839;
type emp_detp_record is table of emp_dept_cur%rowtype;
emp_dept emp_detp_record;
begin
open emp_dept_cur;
loop
fetch emp_dept_cur bulk collect into emp_dept;
exit when emp_dept.count=0;
null;
end loop;
close emp_dept_cur;
end;
/
Two problems with your code... The error at line 4 is caused by the name you chose for your attribute; change emp to x, and dept to y in line 5, and the declaration will work.
Then in the body of your procedure you fetch data from a row set. The fact that the row set is created by joining two tables is irrelevant; first the join is computed, and then you extract rows from it and try to separate the values into emp and dept subrows. That is not possible; when the data comes in from the join, the fact it is a join and not a single table is "water under the bridge." If you really want or need to keep the data from emp and from dept in separate attributes you should bring it in from emp and from dept separately.

PL/SQL : i have a function but there is an error : "in a procedure,RETURN can not contain an expression"

Here is my code:
CREATE OR REPLACE FUNCTION customer_city_function(city_in IN VARCHAR2)
RETURN NUMBER
AS
number_cus NUMBER := 0;
CURSOR cus_cur IS
SELECT COUNT(*)
FROM customer
WHERE customer_city = city_in;
BEGIN
IF city_in IS NOT NULL THEN
OPEN cus_cur;
FETCH cus_cur INTO number_cus;
CLOSE cus_cur;
END IF;
RETURN number_cus;
END;
/
and here is warnings:
Error starting at line : 1 in command -
CREATE OR REPLACE FUNCTION customer_city_function(city_in IN VARCHAR2)
RETURN NUMBER
AS
number_cus NUMBER := 0
Error report -
SQL Command: functıon CUSTOMER_CITY_FUNCTION
Failed: Warning: executing is completed with a warning
Error starting at line : 5 in command -
CURSOR cur_cur IS
Error report -
Unknown Command
Error starting at line : 6 in command -
SELECT COUNT(*)
FROM costumer
WHERE customer_city=city_in
Error at Command Line : 8 Column : 25
Error report -
SQL Error: ORA-00904: "CITY_IN": undefined variable
00904. 00000 - "%s: invalid identifier"
*Cause:
*Action:
Error starting at line : 9 in command -
BEGIN
IF city_in IS NOT NULL
THEN
OPEN cus_cur;
FETCH cus_cur INTO number_cus;
CLOSE cus_cur;
END IF;
RETURN (number_cus);
END;
Error report -
ORA-06550: row 2, column 6:
PLS-00201: 'CITY_IN' variable should been defined
ORA-06550: row 2, column 3:
PL/SQL: Statement ignored
ORA-06550: row 8, column 1:
PLS-00372: in a procedure, RETURN can not contain an expression
ORA-06550: row 8, column 1:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
Where is my mistake? I can't find it, it doesn't make any sense.
(I translated this warning message from my language. I hope I did it right.)
I have just tried it in Command Window and it works. Why doensn't it work in Oracle SQL Developer sql worksheet?
There is nothing wrong with your posted code. The issue might be with your client or the way you are compiling the code.
As you have mentioned PL/SQL Developer in the tags, it might be possible that you have some extra characters in the SQL Worksheet and you are compiling the function as a script, thus the compiler finds it erroneous.
Here is a demo in SQL*Plus, and there is no error:
SQL> CREATE OR REPLACE FUNCTION customer_city_function(i_deptno IN number)
2 RETURN NUMBER
3 AS
4 number_cus NUMBER := 0;
5 CURSOR cus_cur IS
6 SELECT COUNT(*)
7 FROM emp
8 WHERE deptno=i_deptno;
9 BEGIN
10 IF i_deptno IS NOT NULL
11 THEN
12 OPEN cus_cur;
13 FETCH cus_cur INTO number_cus;
14 CLOSE cus_cur;
15 END IF;
16 RETURN number_cus;
17 END;
18 /
Function created.
SQL> sho err
No errors.
SQL> SELECT customer_city_function(10) FROM DUAL;
CUSTOMER_CITY_FUNCTION(10)
--------------------------
3
SQL>
The only difference in my code is that I have used EMP table instead of CUSTOMERS table and the input parameter is DEPTNO instead of CITY_IN. Rest everything is same and function compiles and executes without any errors.

Resources