Exception inside if condition in plsql - oracle

I have a cursor for inserting employee data from temp table to main table. I have a scenario in which first it will check if temp table department id is exist in main department table; if DeptId does not exist then don't insert employee and update ERR_MSG column in temp table. I am handling exception inside if condition after INSERT statement, but it is giving me an error like
Encountered symbol EXCEPTION when expecting one of the following : begin,end,case,else......
sample code is as below:-
DECLARE
--var list
BEGIN
OPEN ltempCur For
-- here i am selecting cols from temp table in variables
LOOP
FETCH ltempCur
INTO
--all the declared variables here
EXIT
WHEN ltempCur %NOTFOUND;
BEGIN
--select statement for checking if employee record exist in table
IF(lExist == 0) --if emloyee record not exist
THEN
begin
--check if dept exist in dept table if not exist then i have assigned zero to deptid variable in NO_DATA_FOUND exception
end;
IF(vardeptid > 0) --if condition for which i have mentioned in description
--Insert statement for employee
EXCEPTION
WHEN OTHERS
THEN
--handling exp
COMMIT;
END;
END IF; -- dept id check if end
--end loop -- close cursor
In above code, if I remove deptid IF ELSE condition then it is working fine, but with that IF condition it is giving error

There is a single end if against two IF clauses. Probably, you have not ended the IF clause for variable lExists.

Related

I am getting no data found error in pl/sql

I am getting no data found error in pl/sql
Actually problem is in the trigger
I want to use NO_DATA_FOUND error in the elsif statement
alter table SUPPLIER add trusted_supplier VARCHAR(30)
and then update it with the data that I load in the table
UPDATE SUPPLIER SET trusted_supplier ='Exotic Liquids'
while using the select statement I have only one value in the trusted_supplier so if insert value in the product is not equal to that
trusted supplier value I am getting error as no data found
is there any way i use NO_DATA_FOUND error which is predefined in pl/sql in the else if statement
CREATE OR REPLACE TRIGGER CHECK_SUPPLIER
BEFORE INSERT ON PRODUCT
FOR EACH ROW
DECLARE
supplier_info varchar(400);
except1 exception;
begin
select SUPPLIER_NAME
INTO supplier_info
FROM PRODUCT P JOIN SUPPLIER S
ON S.COMPANY_NAME = P.SUPPLIER_NAME
where S.trusted_supplier = :NEW.SUPPLIER_NAME ; here
if(supplier_info = 'Exotic Liquids') then
dbms_output.put_line('trusted supplier')
elsif
---------here
END IF;
exception
when except1 then
dbms_output.put_line('its not the trusted supplier');
END;
/

I am getting an error message in Oracle SQL stored procedure

I am trying the following code
CREATE OR REPLACE PROCEDURE sal2
AS
BEGIN
SELECT sal
FROM emp
END
And I'm getting this error
Error at line 7: PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following:
( begin case declare end exception exit for goto if loop mod
null pragma raise return select update while with
<< continue close current delete fetch lock
insert open rollback savepoint set sql execute commit forall
merge pipe purge
5. from emp
6. return 1
7. END
What I want to do is to get a sal column from emp table.
There are multiple issues with code as following;
create or replace procedure sal2
AS
Lv_var number; -- added variable for holding select value
BEGIN
select sal
Into lv_var -- into is needed in select
from emp; -- you missed this semicolon
-- you must use where clause as into variable can hold single value
-- so you must restrict this query to return only 1 record.
END; -- you missed this semicolon
/
Cheers!!
First you have to put the semicolon at the end of each line and after the END keyword. Then the SELECT statement is also wrong you have to load the result in a variable.
Here is the solution for multiple rows.
CREATE OR REPLACE PROCEDURE sal2
AS
CURSOR c_salaries IS SELECT salary FROM employees;
TYPE t_salaries IS TABLE OF c_salaries%rowtype INDEX BY BINARY_INTEGER;
v_salaries t_salaries;
BEGIN
OPEN c_salaries;
FETCH c_salaries BULK COLLECT INTO v_salaries;
CLOSE c_salaries;
END;
And one for a single row result.
CREATE OR REPLACE PROCEDURE sal2
AS
v_salary employees.salary%rowtype;
BEGIN
SELECT salary INTO v_salary
FROM employees WHERE employee_id = 100;
END;

Inserting into a table using a procedure only if the record doesn't exist yet

I have a table that i'm trying to populate via a plsql script (runs on plsql developer). The actual DML statement
is contained in a procedure inside a package. The procedure only inserts if the record doesn't exist yet.
It doesn't work. The part that checks for existence returns true after the first iteration of the script loop even if it doesn't actually exist in the table.
If i put the commit outside of the loop, nothing gets inserted at all and the existence checks return true for all iteration even if the table it empty.
When i try to simplify the insert with existence check to be in just one statement without the exception handling, i get the same outcome.
Please tell me what I'm doing wrong here.
CREATE OR REPLACE PACKAGE BODY some_package
IS
PROCEDURE add_to_queue(id IN NUMBER)
IS
pending_record VARCHAR2(1);
BEGIN
-- this part succeeds even if nothing matches the criteria
-- during the loop in the outside script
SELECT 'Y'
INTO pending_record
FROM dual
WHERE EXISTS (SELECT 'x' FROM some_queue smq
WHERE smq.id = id AND smq.status IS NULL);
EXCEPTION
WHEN NO_DATA_FOUND THEN
INSERT INTO some_queue (seqno, id, activity_date)
VALUES (some_sequence.nextval, id, SYSDATE);
WHEN OTHERS THEN
NULL;
END;
END some_package;
CREATE TABLE some_queue
(
seqno VARCHAR2(500) NOT NULL,
id NUMBER NOT NULL,
activity_date DATE NOT NULL,
status VARCHAR2(25),
CONSTRAINT some_queue_pk PRIMARY KEY (seqno)
);
-- script to randomly fill in the table with ids from another table
declare
type ids_coll_tt is table of number index by pls_integer;
ids_coll_table ids_coll_tt;
cursor ids_coll_cur is
select tab.id
from (select *
from ids_source_table
order by dbms_random.value ) tab
where rownum < 10;
begin
open ids_coll_cur;
fetch ids_coll_cur bulk collect into ids_coll_table;
close ids_coll_cur;
for x in 1..ids_coll_table.count
loop
some_package.add_to_queue(ids_coll_table(x));
commit; -- if this is here, the first iteration gets inserted
end loop;
-- commit; -- if the commit is done here, nothing gets inserted
end;
Note: I translated this code to be more generic for posting. Forgive me if there are any typos.
Update: even if i put everything inside the script and not use the package, i'm not able to properly check for existence and I get the same results.
I figured out the solution:
CREATE OR REPLACE PACKAGE BODY some_package
IS
PROCEDURE add_to_queue(p_id IN NUMBER)
IS
pending_record VARCHAR2(1);
BEGIN
-- this part succeeds even if nothing matches the criteria
-- during the loop in the outside script
SELECT 'Y'
INTO pending_record
FROM dual
WHERE EXISTS (SELECT 'x' FROM some_queue smq
WHERE smq.id = p_id AND smq.status IS NULL);
EXCEPTION
WHEN NO_DATA_FOUND THEN
INSERT INTO some_queue (seqno, id, activity_date)
VALUES (some_sequence.nextval, p_id, SYSDATE);
WHEN OTHERS THEN
NULL;
END;
END some_package;
changing the parameter name fixed it. I guess the compiler gets confused if it's the same name as the table field.
Don't name the parameter the same as the column (use a prefix like p_ or in_) and you can do it in a single statement if you use a MERGE statement self-joining on the ROWID pseudo-column:
CREATE OR REPLACE PACKAGE BODY some_package
IS
PROCEDURE add_to_queue(
in_id IN NUMBER
)
IS
BEGIN
MERGE INTO some_queue dst
USING ( SELECT ROWID AS rid
FROM some_queue
WHERE id = in_id
AND status IS NULL ) src
ON ( src.rid = dst.ROWID )
WHEN NOT MATCHED THEN
INSERT (seqno, id, activity_date)
VALUES (some_sequence.nextval, in_id, SYSDATE);
END;
END some_package;

Oracle PL/SQL Cursor in Trigger

I got this trigger, seems to be alright but i got the error :
Trigger :
CREATE OR REPLACE TRIGGER TRG_TABLE_BI
BEFORE INSERT
ON TABLE
FOR EACH ROW
DECLARE
CURSOR cur_list IS
SELECT emp, name, day, salary, id,phone
FROM TABLE NATURAL JOIN OTHERTABLE
WHERE emp = :NEW.emp AND name = :NEW.name AND id = :NEW.id;
curChoice cur_list%ROWTYPE;
BEGIN
OPEN cur_list;
LOOP
FETCH cur_list INTO curChoice;
EXIT WHEN cur_list%NOTFOUND;
dbms_output.put_line(curchoice.id);
dbms_output.put_line(curChoice.emp);
dbms_output.put_line(curchoice.name);
END LOOP;
CLOSE cur_list;
END;
/
I got those error :
PLS-00049: bad bind variable 'NEW.emp'
If i remove the ':' in the cursor declaration in my WHERE clause, i got a lot more error
Thank you.
Ok, i found the error, in my cursor declaration in the WEHRE clause, i had to remove
emp = :NEW.emp AND name = :NEW.name
because there's no such column in the table that im currently inserting.
Thank !

How to create a delete stored procedure making sure it cannot be deleted when it has affiliated records in another table?

I have tables
supplier( supplier_id (pk), name, address) supplier_invoice( supp_invoice-id(pk), balance)
supplier_product (supp_prod_id(pk), Supplier_id(fk), product_id(fk), supp_invoice_id(fk))
I am trying to execute a delete procedure:
set serveroutput on;
create or replace
procedure delete_supp
(d_supplier_id int)
is
v_count int;
begin
select count(*) into v_count from supplier_product where d_supplier_id=supplier_id;
if v_count > 0 then
dbms_output.put_line('Supplier cannot be deleted because there is an existing invoice in the system');
else
begin
delete from supplier where supplier_id=d_supplier_id;
DBMS_OUTPUT.PUT_LINE('Deleted ' || SQL%ROWCOUNT || ' Rows.');
commit;
end;
end if;
Exception
when others then
dbms_output.put_line('Delete failed');
end;
/
This procedure works but rather than checking if the record exists in supplier_product, I want to make sure a supplier cannot be deleted if he has open invoice in the supplier_invoice table. I tried with looping in supplier_invoice table but couldn't make it to work.
Small change to your delete statement
DELETE FROM supplier
WHERE supplier_id = d_supplier_id
AND NOT EXISTS (SELECT 1
FROM supplier_product,
supplier_invoice
WHERE supp_invoice_id = supp_invoice_id
AND supplier_id = d_supplier_id);
IF SQL%ROWCOUNT = 0 THEN
RAISE Invoice_exists_exception;
END IF;
and this will ensure that supplier records will be deleted only if no records with the same supplier_id & the linked invoice id exists in the supplier_product table.
Of course, if the FKs are set up (as you mention) - then it should raise an exception when you're trying to delete..
Update: I used SQLFiddle to build a sample schema/data to show this:
If you have Foreign keys set up, you'll run into a ORA-02292: integrity constraint violated exception which you can trap & handle appropriately.

Resources