PL/SQL compilation error with declaring variable - oracle

I am trying to create a basic PL/SQL query where I am using a certain SKU as a parameter so that I can reference it without typing in the sku each time.
When compiling my code I get the error:
Error report:
ORA-06550: line 6, column 1:
PLS-00428: an INTO clause is expected in this SELECT statement
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
Here is my code:
declare
myitem number (20);
begin
myitem := 1000956;
select f.order_no
from fdt_maptool f
where f.item = myitem;
end;
/
I thought that maybe it had to do with me using VARCHAR(20) instead of NUMBER, So I tried that as well.
declare
myitem number;
begin
myitem := 1000956;
select f.order_no
from fdt_maptool f
where f.item = myitem;
end;
/
And then received this error:
Error report:
ORA-06550: line 6, column 1:
PLS-00428: an INTO clause is expected in this SELECT statement
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
I am fairly new to PL/SQL so if please go easy on me!

Within PLSQL you need to select into
declare
myitem number(20);
myorder number(20);
begin
myitem := 1000956;
select f.order_no
into myorder
from fdt_maptool f
where f.item = myitem;
end;
/
Now there's two standard things that might go wrong. You may not find a record or you may find more than one record. You need exception handlers to handle these cases.
declare
myitem number(20);
myorder number(20);
begin
myitem := 1000956;
select f.order_no
into myorder
from fdt_maptool f
where f.item = myitem;
exception
when no_data_found then
dbms_output.put_line('No record with this ID');
-- Only needed when not selecting a unique column.
when too_many_rows then
dbms_output.put_line('More than one record with this ID');
end;
/
Note that the too_many_rows exception is usually already covered by the fact that you are selecting an ID column that has a unique constraint defined on it.

Related

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;
/

Can I use INSERT ALL with multiple recordtype variables?

Given a PL/SQL block where I have access to 2 recordtype variables, I want to insert these 2 records into the same table in a single statement, but my attempts to use INSERT ALL have failed thus far. Is it possible to use INSERT ALL with record variables at all?
Here is some code that works, using dedicated inserts:
DECLARE
mProperty1 MyTable%ROWTYPE;
mProperty2 MyTable%ROWTYPE;
...
BEGIN
...
INSERT INTO MyTable VALUES mProperty1;
INSERT INTO MyTable VALUES mProperty2;
...
END;
If I try to convert the statement to a INSERT ALL though, it fails with an error message:
DECLARE
mProperty1 MyTable%ROWTYPE;
mProperty2 MyTable%ROWTYPE;
...
BEGIN
...
INSERT ALL
INTO MyTable VALUES mProperty1
INTO MyTable VALUES mProperty2
SELECT 1 FROM DUAL;
...
END;
ORA-06550: line 14, column 60:
PLS-00382: expression is of wrong type
ORA-06550: line 13, column 60:
PLS-00382: expression is of wrong type
ORA-06550: line 13, column 60:
PL/SQL: ORA-00904: : invalid identifier
ORA-06550: line 12, column 7:
PL/SQL: SQL Statement ignored
Am I missing something obvious? Is there a way to make this statement work?
I have tried using different methods but succeeded with the only following:
Method 1:
Using particular record names from %ROWTYPE field
DECLARE
mProperty1 MyTable%ROWTYPE;
mProperty2 MyTable%ROWTYPE;
BEGIN
mProperty1.COL1 := 1;
mProperty2.COL1 := 2;
INSERT ALL
INTO MyTable VALUES (mProperty1.col1)
INTO MyTable VALUES (mProperty2.col1)
SELECT 1 FROM DUAL;
END;
/
-- may be bad choice but you can use like this
Method 2:
If you are concerned about performance then you can also use this method:
DECLARE
TYPE mProperty_TYPE IS TABLE OF MyTable%ROWTYPE;
mProperty mProperty_TYPE;
BEGIN
mProperty := mProperty_TYPE();
mProperty.EXTEND(2);
mProperty(1).COL1 := 3;
mProperty(2).COL1 := 4;
FORALL I IN 1..mProperty.COUNT
INSERT INTO MyTable VALUES mProperty(I);
END;
/
db<>fiddle demo

How do I display a nested table in Oracle - PL/SQL?

I have an assignment where I'm supposed to create a user-defined function that will return all employees after 1968. My code is as follows:
First I create a new object, called emp_dobs, to hold the employees' firstname, lastname, and date of birth, using the same data types as the original employee table:
CREATE OR REPLACE TYPE emp_dobs AS OBJECT (
emp_fname VARCHAR2(20),
emp_lname VARCHAR2(20),
emp_dob DATE
);
/
Then I create emp_dobs_nested as a table of emp_dobs:
CREATE OR REPLACE TYPE emp_dobs_nested AS TABLE OF emp_dobs;
/
Lastly, I create a function that's supposed to return an emp_dobs_nested table:
CREATE OR REPLACE FUNCTION get_emp_dobs RETURN emp_dobs_nested
AS
dobs emp_dobs_nested;
BEGIN
SELECT emp_dobs(firstname, lastname, birthdate) BULK COLLECT INTO dobs
FROM employee
WHERE birthdate < TO_DATE('01-JAN-1968', 'DD-MON-YYYY');
RETURN dobs;
END;
/
There is a weird quirk with compiling emp_dob_nested, however, where Oracle SQL Developer will display a new tab labeled "Output Variables - Log," and only show EMP_FNAME and EMP_LNAME. Despite that, everything compiles.
Now I want to test the function and display its results to prove that it works, but when I try this:
DECLARE
dobs emp_dobs_nested;
BEGIN
dobs := get_emp_dobs;
DBMS_OUTPUT.PUT_LINE(dobs);
END;
/
I get this error:
Error report -
ORA-06550: line 5, column 5:
PLS-00306: wrong number or types of arguments in call to 'PUT_LINE'
ORA-06550: line 5, column 5:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
What am I missing here? Thanks.
You cannot pass the whole collection to DBMS_OUTPUT, rather you must loop through it and display individual columns at each index.
DECLARE
dobs emp_dobs_nested;
BEGIN
dobs := get_emp_dobs;
FOR i IN 1..dobs.COUNT
LOOP
DBMS_OUTPUT.PUT_LINE(dobs(i).emp_fname||','||dobs(i).emp_lname||','||dobs(i).emp_dob);
END LOOP;
END;
/
You can also use TABLE function to unnest a collection of objects into a relational resultset:
select * from table( get_emp_dobs )
Live demo: http://sqlfiddle.com/#!4/8cfb2/1
Another way of display is to use XML, try
DBMS_OUTPUT.PUT_LINE(XMLTYPE(dobs));
why not a create a view instead?
CREATE VIEW emp_view
AS
SELECT firstname, lastname, birthdate
FROM employee
WHERE birthdate < TO_DATE('01-JAN-1968', 'DD-MON-YYYY');
You can also try this,
DECLARE
dobs emp_dobs_nested;
i NUMBER := 0;
BEGIN
dobs := get_emp_dobs;
LOOP
i := dobs.NEXT(i);
DBMS_OUTPUT.PUT_LINE(dobs(i).emp_fname||','||dobs(i).emp_lname||','||dobs(i).emp_dob);
IF i = dobs.LAST THEN
EXIT;
END IF;
END LOOP;
END;
/

BULK Collect into misleading error messages for ORA-00913 & ORA-00947

desc book_data;
Name Null Type
---------- ---- ------------
BOOK_NAME VARCHAR2(50)
BOOK_PRICE NUMBER
BOOK_SSN VARCHAR2(50)
DECLARE
TYPE book_rec is record(
book_name varchar2(50),
book_price number,
book_ssn varchar2(50)
);
type book_tbl_type is table of book_rec;
book_tbl1 book_tbl_type := book_tbl_type();
BEGIN
SELECT BOOK_NAME, BOOK_PRICE/*,book_ssn,1*/ BULK COLLECT INTO book_tbl1 FROM book_data;
DBMS_OUTPUT.put_line(book_tbl1(1).book_name);
END;
Error report -
ORA-06550: line 11, column 75:
PL/SQL: ORA-00913: too many values
ORA-06550: line 11, column 3:
PL/SQL: SQL Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
Question : Here we are inserting two columns into three column collection table Then We Should have got "ORA-00947: not enough values" error.But We are getting "ORA-00913: too many values". Why ?
DECLARE
TYPE book_rec is record(
book_name varchar2(50),
book_price number,
book_ssn varchar2(50)
);
type book_tbl_type is table of book_rec;
book_tbl1 book_tbl_type := book_tbl_type();
BEGIN
SELECT BOOK_NAME, BOOK_PRICE,book_ssn,1 BULK COLLECT INTO book_tbl1 FROM book_data;
DBMS_OUTPUT.put_line(book_tbl1(1).book_name);
END;
Error report -
ORA-06550: line 11, column 71:
PL/SQL: ORA-00947: not enough values
ORA-06550: line 11, column 3:
PL/SQL: SQL Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
Question : Here we are inserting four columns into three column collection table . Then We Sould have got "ORA-00913: too many values" error .
But We are getting "ORA-00947: not enough values". Why ?
ORA-00913 too many values
Cause: The SQL statement requires two sets of values equal in number. This error occurs when the second set contains more items than the first set. For example, the subquery in a WHERE or HAVING clause may return too many columns, or a VALUES or SELECT clause may return more columns than are listed in the INSERT.
Action: Check the number of items in each set and change the SQL statement to make them equal.
In case of BULK COLLECT it seems that the error message refers to the number of columns in collection table, not to the number of selected columns..
To avoid similar problems you can use %ROWTYPE, something like that:
DECLARE
type book_tbl_type is table of book_data%ROWTYPE;
book_tbl1 book_tbl_type := book_tbl_type();
BEGIN
SELECT b.* BULK COLLECT INTO book_tbl1 FROM book_data b;
END;
/

PL SQL Stored Procedure for new Transaction and order

I'm giving a small snippet of my code but I 'm receiving the below error when trying to create a new order for a stored Oracle pl sql procedure.
line 83 is the insert statement in the code and line 84 is in the insert part of the statement.
83/5 PL/SQL: SQL Statement ignored
84/47 PL/SQL: ORA-00984: column not allowed here
BEGIN
--Initializing values for variables
x_rowcount := 0;
x_stockonhand := 0;
Totaldue := 0;
--Total due calculation
--(price of phone*quantity + shipping cost)*1.06 (assuming 6% sales tax)
Totaldue := (((i_price * c_p_qty) + i_shipping_cost) * 1.06);
SAVEPOINT start_transaction; -- mark a savepoint
--INSERT a new record into order table.
INSERT INTO orders(o_id,c_id,p_id,s_id,order_date,o_qty,order_total,card_type,cc_number,exp_date,shipping_status)
VALUES (orders_seq.nextval, c_c_id,c_p_id,s_id,sysdate,c_p_qty,Totaldue,c_card_type,c_cc_number,c_exp_date,'Not shipped yet');
Check your declaration section. Usually this error appears when you make a typo in variable name or variable not declared. For example:
SQL> create table tmp (id number, str varchar2(100));
Table created.
SQL> declare
a number;
begin
insert into tmp (id, str)
values (a, a1);
end;
/
values (a, a1);
*
ERROR at line 5:
ORA-06550: line 5, column 14:
PL/SQL: ORA-00984: column not allowed here
ORA-06550: line 4, column 3:
PL/SQL: SQL Statement ignored
The error is because one or more of the values in your VALUES(...,...) section is invalid.
I would suggest checking each one to see that they are valid. For example, is c_c_id declared and given a value somewhere else in the code? If not, this is likely your problem. Each one needs to be declared and given a value before it can be put in the VALUES(...,...) section of the INSERT statement.
INSERT INTO orders(o_id,c_id,p_id,s_id,order_date,o_qty,order_total,card_type,cc_number,exp_date,shipping_status)
VALUES (orders_seq.nextval, c_c_id,c_p_id,s_id,sysdate,c_p_qty,Totaldue,c_card_type,c_cc_number,c_exp_date,'Not shipped yet');

Resources