Issue with PL-SQL: ORA-06550 - sql

I'm trying to learn a bit of PL-SQL using a tutorial by examples book, but one of the suggested codes return the following error when run:
ORA-06550: line 10, column 48: PL/SQL: ORA-00947: not enough values
ORA-06550: line 9, column 1: PL/SQL: SQL Statement ignored
Could you please help me understand what I'm doing wrong?
Many thanks in advance!
Simone.
SQL Fiddle
Oracle 11g R2 Schema Setup:
create table product (code integer primary key, name varchar2 (20), type varchar2(8),price number(4,2),update_dt date);
insert into product values(1,'Mela','Frutta',1,to_date('1-MAY-2015','DD-MON-YYYY'));
insert into product values(2,'Pera','Frutta',2,to_date('2-MAY-2015','DD-MON-YYYY'));
insert into product values(3,'Carota','Ortaggio',3,to_date('3-MAY-2015','DD-MON-YYYY'));
insert into product values(4,'Zucchina','Ortaggio',4,to_date('4-MAY-2015','DD-MON-YYYY'));
insert into product values(5,'Arancia','Frutta',5,to_date('5-MAY-2015','DD-MON-YYYY'));
Query 1:
declare
code_var integer;
type_var varchar2(8);
name_var varchar2(20);
price_var number(4,2);
update_dt_var date;
price_too_high exception;
begin
select code, type,name, price, update_dt
into code_var,type_var,price_var,update_dt_var
from product
where name='Arancia';
if price_var > 4.5 then
raise price_too_high;
end if;
exception
when price_too_high then
dbms_output.put_line('price is too damn high!');
end;
Results:

you are trying to insert 5 values from your select into four variables.

This is correct:
select code, type, name, price, update_dt
into code_var, type_var, name_var, price_var, update_dt_var
from product
where name='Arancia';

Related

Oracle PLSQL fetch multiple row/column value of number data type into a collection of number type?

We have a table that was designed to have multiple columns with number data types that stores a primary key from another table. Each row has a unique organization id. So the structure looks like this.
create table matrix_table (
id number primary key
, emp_id1 number
, emp_id2 number
, emp_id3 number
, emp_id4 number
)
/
insert into matrix_table values ( 1, 100, 101, 102, 103 )
/
insert into matrix_table values ( 2, 200, 201, 202, 203 )
/
insert into matrix_table values ( 3, 300, 301, 302, 303 )
/
insert into matrix_table values ( 4, 400, 401, 402, 403 )
/
create type emp_ids is table of number
/
Then I try to do it like this but it doesn't work since it is expecting a collection of emp_ids
declare
l_emp_ids emp_ids := emp_ids();
begin
select emp_ids(emp_id1, emp_id2, emp_id3, emp_id4)
bulk collect
into l_emp_ids
from matrix_table;
end;
ORA-06550: line 4, column 12: PL/SQL: ORA-00932: inconsistent datatypes: expected NUMBER got APPS.EMP_IDS
ORA-06550: line 4, column 5: PL/SQL: SQL Statement ignored
I also tried without the bulk collect but again it won't work since it is expecting only 1 record whereas I have 4.
declare
l_emp_ids emp_ids := emp_ids();
begin
select emp_ids(emp_id1, emp_id2, emp_id3, emp_id4)
into l_emp_ids
from matrix_table;
end;
ORA-01422: exact fetch returns more than requested number of rows
ORA-06512: at line 4
I know this can via union or thru loop but I was wondering if there is a simpler way to do it.
Reason I'm doing this is because later on I need to join this with another table. Kind of like this.
select e.*
from employees e
, table ( emp_ids_var ) v
where e.emp_id = v.column_value
For reference, here's our database details:
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
PL/SQL Release 12.1.0.2.0 - Production
CORE 12.1.0.2.0 Production
TNS for Linux: Version 12.1.0.2.0 - Production
NLSRTL Version 12.1.0.2.0 - Production
Appreciate any feedback.
As far as I know, we need to create an object type first.
create type obj_ids is object (
emp_id1 number
, emp_id2 number
, emp_id3 number
, emp_id4 number
);
create type emp_ids is table of obj_ids;
And this should work:
declare
l_emp_ids emp_ids := emp_ids();
begin
select obj_ids(emp_id1, emp_id2, emp_id3, emp_id4)
bulk collect
into l_emp_ids
from matrix_table;
for i in 1..l_emp_ids.count
loop
dbms_output.put_line (l_emp_ids(i).emp_id1);
end loop;
end;

Oracle SQL - How to define a date bind variable based on a select statement

Using Oracle SQL, I have several SQL Queries with manual bind variables that are used to create a table as follows:
What I would like to do is to change the define anfang to (select c_year_beginning from master_date_automation).
I have tried several combinations of bind variables but could not make it work (edited with DEL comments):
begin
execute immediate 'DROP TABLE A_TEST_TABLE'
end;
/
begin
execute immediate 'create table A_TEST_TABLE (
user varchar2(100),
product varchar2(100),
datum date)';
end;
/
BEGIN
DECLARE
v_c_year_ytd DATE;
BEGIN
SELECT c_year_ytd Into v_c_year_ytd FROM master_date_automation;
BEGIN
SELECT usr.datum || ','
|| usr.user || ','
|| usr.product
INTO A_TEST_TABLE
FROM users_table usr
WHERE usr.datum = v_c_year_ytd
AND kto.kontonummer = '00510199065';
END;
END;
END;
ERROR message (edited after Del comment):
Error report -
ORA-06550: line 12, column 6:
PLS-00403: expression 'A_TEST_TABLE' cannot be used as an INTO-target of a SELECT/FETCH statement
ORA-06550: line 12, column 21:
PL/SQL: ORA-00904: : invalid identifier
ORA-06550: line 9, column 1:
PL/SQL: SQL Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
Would be really thankful if someone could help me out.
Thousand thanks in advance!
So, to sum up my comments from above, you don't need PL/SQL to do this. You could do all of your script with straight SQL:
CREATE TABLE A_TEST_TABLE
(
user varchar2(100),
product varchar2(100),
datum date
);
INSERT INTO a_test_table
SELECT usr.user,
usr.product,
usr.datum
FROM users_table
WHERE usr.datum = (SELECT c_year_ytd FROM master_date_automation)
AND usr.user= '123456789'
Drop the table if you need to first.
You don't need to use dynamic SQL inside a PL/SQL block to create the tables; you can do it using SQL statements:
DROP TABLE A_TEST_TABLE;
CREATE TABLE A_TEST_TABLE (
user_name varchar2(100),
product varchar2(100),
datum date
);
Note: USER is a reserved word and you CANNOT use it as an unquoted identifier; you will need to find another identifier such as user_name or you will have to use a quoted identifer and refer to it as "USER" everywhere it is used (however, that is bad practice).
Then if you want to use PL/SQL you can use:
DECLARE
v_c_year_ytd DATE;
BEGIN
SELECT c_year_ytd
Into v_c_year_ytd
FROM master_date_automation;
INSERT INTO a_test_table (datum, user_name, product)
SELECT datum,
user_name
product
FROM users_table
WHERE datum = v_c_year_ytd
AND kontonummer = '00510199065';
END;
/
But it would be much simpler to just use one SQL statement:
INSERT INTO a_test_table (datum, user_name, product)
SELECT datum,
user_name
product
FROM users_table
WHERE datum = (SELECT c_year_ytd FROM master_date_automation)
AND kontonummer = '00510199065';

Audit Table Trigger

Trying to create a trigger for populating an audit table with old data before changes are made to the base table BOOKS
CREATE OR REPLACE TRIGGER populate_audit_table
BEFORE INSERT OR UPDATE OF cost, retail OR DELETE
ON books
REFERENCING NEW as new OLD as old
FOR EACH ROW
DECLARE
dml_operation varchar2(1) :=
CASE WHEN UPDATING THEN 'U'
WHEN DELETING THEN 'D'
ELSE 'I'
END;
BEGIN
INSERT INTO cost_retail_history
(isbn
,title
,pubid
,pubdate
,cost
,retail
,discount
,category
,dml_operation)
SELECT
(old.isbn
,old.title
,old.pubid
,old.pubdate
,old.cost
,old.retail
,old.discount
,old.category
,new.dml_operation)
FROM BOOKS;
end;
I get the following errors:
Errors: TRIGGER POPULATE_AUDIT_TABLE
Line/Col: 8/7 PL/SQL: SQL Statement ignored
Line/Col: 20/13 PL/SQL: ORA-00907: missing right parenthesis
I also tried using VALUES on the INSERT INTO and not designating a source table ("FROM BOOKS")
....VALUES
(old.isbn
,old.title
,old.pubid
,old.pubdate
,old.cost
,old.retail
,old.discount
,old.category
,new.dml_operation);
end;
And I get the following errors:
Line/Col: 8/7 PL/SQL: SQL Statement ignored
Line/Col: 27/18 PL/SQL: ORA-00984: column not allowed here
I've read and re-read https://docs.oracle.com/cd/A64702_01/doc/server.805/a58225/ch4a.htm#1997457 so I feel like I'm missing something simple and just need a point in the right direction.
Thanks,
EDIT:
I dropped the dml_operation as this wasn't required and followed the advice below, but I am still getting errors:
Current version:
CREATE OR REPLACE TRIGGER cost_retail_history
BEFORE INSERT
OR UPDATE OF cost, retail
OR DELETE
ON books
REFERENCING NEW as new OLD as old
FOR EACH ROW
BEGIN
CASE
WHEN INSERTING THEN
INSERT INTO cost_retail_history
(isbn
,title
,pubid
,pubdate
,cost
,retail
,discount
,category)
VALUES
(:new.isbn
,:new.title
,:new.pubid
,:new.pubdate
,:new.cost
,:new.retail
,:new.discount
,:new.category)
WHEN UPDATING cost, retail OR DELETING THEN
INSERT INTO cost_retail_history
(isbn
,title
,pubid
,pubdate
,cost
,retail
,discount
,category)
VALUES
(:old.isbn
,:old.title
,:old.pubid
,:old.pubdate
,:old.cost
,:old.retail
,:old.discount
,:old.category);
END CASE;
END;
I'm getting the errors:
Errors: TRIGGER COST_RETAIL_HISTORY
Line/Col: 4/9 PL/SQL: SQL Statement ignored
Line/Col: 22/5 PL/SQL: ORA-00933: SQL command not properly ended
I can't tell exactly what line the error is on as this would indicate it's with:
...OR DELETE
and
... ,:new.title
which does not make sense to me.
If you were doing insert ... select ... then you should not have the parentheses around the column list; i.e.:
INSERT INTO cost_retail_history
(isbn
...
,dml_operation)
SELECT
old.isbn
...
,new.dml_operation
FROM BOOKS;
but you should not be selecting from the table the trigger is against - partly because you'll get a mutating table error, and you are attempting to insert an audit row for every row in the base table; but mostly because you already have all of the information you need.
With the values clase you need to prefix the old/new values with a colon:
....VALUES
(:old.isbn
,:old.title
,:old.pubid
,:old.pubdate
,:old.cost
,:old.retail
,:old.discount
,:old.category
,:new.dml_operation);
end;
Read more in the documentation.
Oracle has built-in audit tools but presumably this is an exercise.
I can't tell exactly what line the error is on as this would indicate...
This can be slightly confusing with triggers as they are a mix of SQL and PL/SQL. Because you are getting PL/SQL errors the line numbering starts from the beginning of the PL/SQL part, so here BEGIN is line 1, INSERT is line 4; WHEN UPDATING... is line 22.
Those new errors are just because you don't have a semicolon at the end of the first INSERT statement:
,:new.discount
,:new.category);
-----------------------^
WHEN UPDATING cost, retail OR DELETING THEN
INSERT INTO cost_retail_history
The error is reported against line 22 because that WHEN is where it's expecting to see the semicolon, and the first point it can see the previous SQL command hasn't been completed. The error against line 4 is saying where that not-ended command started; so you're getting two messages for one actual problem.

How to Insert a stored procedure into sql developer

I'm trying to create an INSERT stored procedure in my database using Oracle SQL Developer but I can't seem to figure out what's the problem with this code;
create or replace procedure insert_order
as
BEGIN
INSERT INTO ORDERS (ORDER_NUM, ORDER_DATE, CONDITION, STATUS, CUSTOMER_CUSTOMER_NUM, CUSTOMER_EMPLOYEE_NUM)
VALUES(1, '30/OCT/2007', 'BRANDNEW', 'ORDERD', 103, 1);
end insert_order;
Can you help please?
The error message PL/SQL: SQL Statement ignored, and Error(5,23): PL/SQL: ORA-00984: column not allowed here indicates that the error is with the value '30/OCT/2007' (line 5, column 23), since you are not using the standard format for dates.
You can try TO_DATE('30/OCT/2007') or '2007-10-30'.

error ORA-06550 ORA-00933

I have a sales table:
Name Null? Type
SALE_ID NOT NULL NUMBER(4)
SALE_DATE DATE
NO_OF_PRODS NUMBER(4)
PROD_ID NOT NULL NUMBER(4)
CUST_ID NOT NULL NUMBER(4)
DESP_ID NOT NULL NUMBER(4)
SALE_RECEIPT NOT NULL NUMBER(5)
I am trying to insert randomly generated data into the sales table. I am using iSQL plus for oracle. This is just test data that I have to create.
I run the following script to generate the data:
begin
insert into sales
select sale_id_seq.nextval,
sysdate,
trunc(dbms_random.value(000,999)),
p.prod_id, c.cust_id
FROM dba_xy.product p, dba_xy.customer c,
desp_id_seq.nextval,
trunc(dbms_random.value(0000,9999));
end;
/
But when I do, the following error message appears:
trunc(dbms_random.value(0000,9999));
*
ERROR at line 9:
ORA-06550: line 9, column 21:
PL/SQL: ORA-00933: SQL command not properly ended
ORA-06550: line 2, column 2:
PL/SQL: SQL Statement ignored.
What have I done wrong?
I just realised that the DESP_ID is a foreign key within the sales table, but currently the despatch table is empty and when I try to insert data into either tables, I'm not able to cause one table needs the data from the other table. I end up getting this error message:
PL/SQL: ORA-02289: sequence does not exist
You cannot select FROM
FROM dba_xy.product p, dba_xy.customer c,
desp_id_seq.nextval,
trunc(dbms_random.value(0000,9999));
Try:
insert into sales
(select
sale_id_seq.nextval,
sysdate,
trunc(dbms_random.value(000,999)),
p.prod_id,
c.cust_id,
desp_id_seq.nextval,
trunc(dbms_random.value(0000,9999))
FROM dba_xy.product p, dba_xy.customer c;
BTW, are you sure that you want an Cartesian product here, maybe some join is missed ?