PL/SQL Block in oracle11g - oracle

I have to the following question but what I have tried keeps giving me an error.
Create a PL/SQL query to display the product name, product price and delivery description. Only display the records where the difference between the despatch date and delivery date is greater than three days. In your query also determine whether the product is a premium or non-premium product.
This is what I have attempted.
set SERVEROUTPUT on;
DECLARE
p_product VARCHAR2(50);
p_price VARCHAR2(50);
d_description VARCHAR2(50);
d_days NUMBER(3.0);
p_productcat VARCHAR2(50);
cursor INFO IS
select p.Product, p.Price, d."Description", d.despatchdate || d.deliverydate as "Delivery Days"
from product p, delivery d
where d.deliverydate ('dd')- d.despatchdate('dd') > 3;
begin
open INFO;
loop
if (p_price > 15000) then
p_productcat:='Premium Product';
else
p_productcat:='Non Premium Product';
end if;
exit when INFO%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('PRODUCT:'|| p_product||chr(30)||'PRICE:'||p_price||chr(13)||'DESCRIPTION:'||
d_description || chr(50) || 'DELIVERY DAYS:' || d_days || chr(13) || 'PRODUCT CATEGORY:' ||
p_productcat);
DBMS_OUTPUT.PUT_LINE('----------------------------------------------');
end loop;
close info;
end;
The error is:
Error starting at line : 254 in command
Error report -
ORA-06550: line 10, column 30:
PL/SQL: ORA-00904: "D"."DESPATCHDATE": invalid identifier
ORA-06550: line 8, column 1:
PL/SQL: SQL Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:

Ah! Mystery! I love that! But - not that much in coding. Saying that there are errors - which errors?
Until you respond, here's what looks suspicious:
d."Description" - unless column is created using double quotes, this won't work. Use d.description instead
don't compare days in a month (unless you're sure that those dates will always be in the same month). Use WHERE d.deliverydate - d.despatchdate > 3. Or, if you insist, apply the TO_CHAR function: WHERE to_char(d.deliverydate, 'dd') - to_char(d.despatchdate, 'dd') > 3

Related

How to avoid this in PLSQL

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.

How to use a variable in a LIKE clause in PL/SQL

I am new to Oracle and learning; I am simply trying to run this T-SQL query
DECLARE #SearchObj varchar(100);
SET #SearchObj='%aldbrough%';
SELECT
obj_id,
name,
description
FROM
agnis.t_object
WHERE
lower(name) = ObjToSearch ;
I am using SQL Developer Oracle tool which also have a "Scratch Editor" to help with translation from T-SQL. When i run the tool it gave me this code
DECLARE
v_SearchObj VARCHAR2(100);
BEGIN
v_SearchObj := '%aldbrough%' ;
SELECT obj_id ,
NAME ,
DESCRIPTION
FROM agnis.t_object
WHERE LOWER(NAME) = ObjToSearch;
END;
but the same tool give me this error
Error report -
ORA-06550: line 10, column 26:
PL/SQL: ORA-00904: "OBJTOSEARCH": invalid identifier
ORA-06550: line 6, column 4:
PL/SQL: SQL Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
so what is the correct syntax to use a variable into a LIKE clause that returns multiple rows?
I hope I do not have to use cursors etc for such of a simple statement as suggested in this question
Well, yes - those "translators" don't always do what they are supposed to.
This is how your code should look like:
use like, not = in the where clause
in PL/SQL, you have to put the result of the select statement into something - for example, locally declared variables (as my example shows).
So:
DECLARE
v_SearchObj VARCHAR2 (100) := '%aldbrough%';
--
v_obj_id t_object.obj_id%TYPE;
v_name t_object.name%TYPE;
v_description t_object.description%TYPE;
BEGIN
SELECT obj_id, NAME, DESCRIPTION
INTO v_obj_id, v_name, v_description
FROM agnis.t_object
WHERE LOWER (NAME) LIKE v_searchobj;
END;
If such a code returns an error - too_many_rows (and yes, it does), then one option is to loop through rows and do something (such as display those values):
DECLARE
v_SearchObj VARCHAR2 (100) := '%aldbrough%';
BEGIN
FOR cur_r IN (SELECT obj_id, NAME, DESCRIPTION
FROM agnis.t_object
WHERE LOWER (NAME) LIKE v_searchobj)
LOOP
DBMS_OUTPUT.put_line (
'Name = ' || cur_r.name || ', description = ' || cur_r.description);
END LOOP;
END;
Since this is tagged SQL Developer, use a bind variable:
SELECT obj_id,
name,
description
FROM agnis.t_object
WHERE lower(name) = :ObjToSearch;
and SQL developer will pop up a dialog box where you can set the value of the ObjToSearch variable.
If you want to specify the bind variable in code then:
VARIABLE objtosearch VARCHAR2(50)
BEGIN
:objtosearch := '%aldbrough%';
END;
/
SELECT obj_id,
name,
description
FROM agnis.t_object
WHERE lower(name) = :ObjToSearch;
And run the statements as a script using F5 rather than as individual statements.

Oracle pl/sql - Use associative array with user created record

I'm trying to use an associative array with the element type of a user defined record. This array is to print the first name, last name, and grade of a student.
SET SERVEROUTPUT ON
DECLARE
TYPE studentRec IS RECORD (
STUDENT_ID studentdb.student.student_id%TYPE,
FIRST_NAME STUDENTDB.STUDENT.FIRST_NAME%TYPE,
LAST_NAME STUDENTDB.STUDENT.LAST_NAME%TYPE,
GRADE STUDENTDB.GRADE.NUMERIC_GRADE%TYPE
);
CURSOR studentCursor IS
SELECT STUDENT.STUDENT_ID, STUDENT.FIRST_NAME, STUDENT.LAST_NAME, AVG(GRADE.NUMERIC_GRADE) AS GRADE
FROM STUDENTDB.STUDENT
INNER JOIN STUDENTDB.GRADE
ON STUDENTDB.STUDENT.STUDENT_ID = STUDENTDB.GRADE.STUDENT_ID
GROUP BY STUDENT.STUDENT_ID, STUDENT.FIRST_NAME, STUDENT.LAST_NAME ;
sr studentRec;
TYPE studentArray IS TABLE OF studentRec INDEX BY PLS_INTEGER;
vars studentArray;
BEGIN
FOR rec IN studentCursor LOOP
vars(rec.STUDENT_ID) := rec.FIRST_NAME || ' ' || rec.LAST_NAME || ' has grade ' || rec.GRADE;
END LOOP;
FOR ind IN vars.FIRST .. vars.LAST LOOP
DBMS_OUTPUT.PUT_LINE(vars(ind));
END LOOP;
END;
This throws:
Error report - ORA-06550: line 27, column 27: PLS-00382: expression is
of wrong type ORA-06550: line 27, column 3: PL/SQL: Statement ignored
ORA-06550: line 33, column 1: PLS-00306: wrong number or types of
arguments in call to 'PUT_LINE' ORA-06550: line 33, column 1: PL/SQL:
Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
You don't need a RECORD declaration here, although you could use it if you know it. It is better to use CURSOR%ROWTYPE. syntax as shown. There is also no need of associative array, as your indexes are going to be numbers anyway.
Also, instead of looping through the CURSOR, you could use BULK COLLECT INTO.
You cannot directly pass vars(ind) to .PUT_LINE() . It should refer to specific column names.
SET serveroutput ON
DECLARE
CURSOR studentcursor IS
SELECT student.student_id,
student.first_name,
student.last_name,
AVG(grade.numeric_grade) AS GRADE
FROM studentdb.student
inner join studentdb.grade
ON studentdb.student.student_id =
studentdb.grade.student_id
GROUP BY student.student_id,
student.first_name,
student.last_name;
TYPE studentarray
IS TABLE OF studentcursor%ROWTYPE;
vars STUDENTARRAY;
BEGIN
OPEN studentcursor;
FETCH studentcursor BULK COLLECT INTO vars;
FOR ind IN vars.first .. vars.last LOOP
dbms_output.put_line(vars(ind).student_id
||','
|| vars(ind).first_name
||','
||vars(ind).last_name
||','
|| vars(ind).grade);
END LOOP;
END;

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.

Getting error while forming Dynamic PLSQL

I am trying to form below SQL statement. but getting this weird error which I can't seem to figure out. I have executed each statement individually outside the loop and they are working fine. Please someone help me finding the error.
Error
ORA-06550: line 6, column 14:
PLS-00306: wrong number or types of arguments in call to '||'
ORA-06550: line 6, column 7:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
PLSQL Statement:
DECLARE
L_sql VARCHAR2(2000):=NULL;
BEGIN
FOR val IN (SELECT generation_qtr from test_1)
LOOP
L_sql:=L_sql ||' MAX(DECODE(generation_qtr, '||''''||val||''''||' cum_actual_gen)) AS ' || val ||','||chr(10);
END LOOP;
L_sql:='SELECT assetname, '|| L_sql;
L_sql:=substr(L_sql,1,LENGTH(L_sql)-1);
dbms_output.put_line(L_sql);
END;
Oracle Version -11.2
You're referring to val directly, but that's a cursor row type. You need to specify the column name, even if there is only one:
... ||val.generation_qtr|| ...
... in both places you use it in the concatenation. So it woudl become:
L_sql:=L_sql ||' MAX(DECODE(generation_qtr, '||''''
|| val.generation_qtr ||''''||' cum_actual_gen)) AS '
|| val.generation_qtr ||','||chr(10);
If you're going to execute this dynamically then the new line characters aren't going to be very useful, but I guess they help for debugging.

Resources