Bind variable error in SQL trigger - sql

Here is my trigger.Following error.
45 /
SP2-0552: Bind variable "OLD" not declared.
I am unable to find the error .I have tried several times but failed.I have declared every variable but the error is showing.Someone please help me .
drop trigger DELETE_Single_food
CREATE OR REPLACE TRIGGER DELETE_Single_food
BEFORE DELETE ON SingleFoodOrder
FOR EACH ROW
declare
f_price number;
old_bill number;
f_quantity number;
p_bill number;
foodID number;
orderID number;
order_date Date;
s_date Date;
f_date Date;
f_dis number;
a number;
b number;
c number;
BEGIN
IF :old.H_delivery_ID is not NULL then
foodID := :old.Fooditem_ID;
orderID := :old.H_delivery_ID;
f_quantity := :old.Quantity;
select bill into old_bill from HomeDelivery where H_delivery_ID =orderID ;
select price into f_price from Food_Item where Fooditem_ID = foodID;
select discount_percentage into f_dis from Food_Item where Fooditem_ID = foodID;
select start_date into s_date from Food_Item where Fooditem_ID = foodID;
select deadline into f_date from Food_Item where Fooditem_ID = foodID;
select H_delivery_request into order_date from HomeDelivery where H_delivery_ID =orderID;
if f_dis is not NULL then
if (order_date >= s_date and order_date<=f_date) then
a := f_dis/100;
b := f_price*a ;
c := f_price-b;
p_bill := old_bill-( c*f_quantity);
update HomeDelivery set bill = p_bill where H_delivery_ID = orderID;
else
p_bill := old_bill-(f_price*f_quantity);
update HomeDelivery set bill = p_bill where H_delivery_ID = orderID;
end if;
else
p_bill := old_bill-(f_price*f_quantity);
update HomeDelivery set bill = p_bill where H_delivery_ID = orderID;
end if;
END;
/

The problem is not in your variables declarations. I think you're not closing your main IF statement:
IF :old.H_delivery_ID is not NULL then
I don't see the END IF for that one. Add END IF; before the END;
If this does not work, you will need to do some debugging. Try just to leave only that statement in the begin block.
CREATE OR REPLACE TRIGGER DELETE_Single_food
BEFORE DELETE ON SingleFoodOrder
FOR EACH ROW
BEGIN
IF :old.H_delivery_ID is not NULL then
null;
END IF;
END;
/
See if that compiles. Then add the rest of the code to see where it breaks.
Hope this helps!

Related

How can i fix a PLS-00306 ERROR inpl/sql?

I want my function price data to takes the ids from the customers and for each item to make a special price..
example:
cust_id | item_id | price
30 14 11
30 25 4
31 14 12
31 25 6
CREATE OR REPLACE FUNCTION PRICE_DATA(
P_CUST_DATA_ID CUSTOMERS.CUSTOMERS_ID%TYPE,
P_ITEMS_DATA_ID ITEMS.ITEMS_ID%TYPE)
RETURN NUMBER AS
L_PRICE NUMBER;
BEGIN
dbms_random.seed(1000);
FOR i IN(SELECT CUSTOMERS_ID FROM CUSTOMERS) LOOP
FOR i IN(SELECT ITEMS_ID FROM ITEMS) LOOP
L_PRICE := ADD_PRICELIST(P_CUST_DATA_ID,
P_ITEMS_PRIC_ID,
ROUND(dbms_random.value(0,10),3));
END LOOP;
END LOOP;
RETURN L_PRICE;
END PRICE_DATA;
I run this script:
DECLARE
L_PRICE_ID NUMBER;
BEGIN
DELETE FROM PRICE;
L_PRICE_ID := PRICE_DATA;
END;
And i get a PLS-00306 ERROR in PRICE DATA
In your function, you have P_ITEMS_PRIC_ID it should be P_ITEMS_DATA_ID. You probably don't want to call both row variables i either.
Assuming your ADD_PRICELIST function does not have side-effects (it should not), you can rewrite it as:
CREATE OR REPLACE FUNCTION PRICE_DATA(
P_CUST_DATA_ID IN CUSTOMERS.CUSTOMERS_ID%TYPE,
P_ITEMS_DATA_ID IN ITEMS.ITEMS_ID%TYPE
)
RETURN NUMBER
AS
L_PRICE NUMBER;
BEGIN
dbms_random.seed(1000);
SELECT ADD_PRICELIST(
p_cust_data_id,
p_items_data_id,
ROUND(dbms_random.value(0,10),3)
)
INTO L_PRICE
FROM customers c
CROSS JOIN items i
ORDER BY c.customers_id DESC, i.items_id DESC
FETCH FIRST ROW ONLY;
RETURN L_PRICE;
END PRICE_DATA;
/
But that seems overkill as you do not use any values from the tables and are effectively just checking that at least one row exists in each table (and inefficiently calling ADD_PRICELIST multiple times) then you can simplify it to just checking the rows exist and then calling the function once:
CREATE OR REPLACE FUNCTION PRICE_DATA(
P_CUST_DATA_ID IN CUSTOMERS.CUSTOMERS_ID%TYPE,
P_ITEMS_DATA_ID IN ITEMS.ITEMS_ID%TYPE
)
RETURN NUMBER
AS
L_PRICE NUMBER;
l_exists NUMBER(1,0);
BEGIN
dbms_random.seed(1000);
SELECT CASE
WHEN EXISTS(SELECT 1 FROM customers)
AND EXISTS(SELECT 1 FROM items)
THEN 1
ELSE 0
END
INTO l_exists
FROM DUAL;
IF l_exists = 1 THEN
l_price := ADD_PRICELIST(
p_cust_data_id,
p_items_data_id,
ROUND(dbms_random.value(0,10),3)
);
END IF;
RETURN L_PRICE;
END PRICE_DATA;
/
Then you need to specify all the arguments when you call the function:
DECLARE
L_PRICE_ID NUMBER;
BEGIN
--DELETE FROM PRICE;
L_PRICE_ID := PRICE_DATA(3.14159, 2.71828);
DBMS_OUTPUT.PUT_LINE(l_price_id);
END;
/
db<>fiddle here

Making procedure to insert/update qty. What am I doing wrong?

I am trying to make procedure that count total slab # of from each pallet from prod_result table and insert or update that count to qty column in plt_result table that has same pallet #(plt_no)
I've tried insert, update both but doesn't work.
create or replace PROCEDURE update_qty
is
v_plt_no nvarchar2(20);
v_qty number;
cursor q1 is
select count(slab_no)
into v_qty
from prod_result
where plt_no = v_plt_no;
begin
if v_qty > 0 then
update plt_result
set qty = 'v_qty'
where plt_no = v_plt_no;
end if;
end;
What am I doing wrong here? Help please.
I'm not sure which version you're looking for - is it the one that loops through all PLT_NOs in a table, or the one that should accept PLT_NO as a parameter. Here are both options, see whether any of them helps.
The first one uses cursor FOR loop; it is easier to maintain as Oracle does most of the dirty job for you (opening the cursor, fetching, exiting the loop, closing the cursor).
create or replace procedure update_qty
is
begin
for cur_r in (select plt_no, count(slab_no) v_qty
from prod_result
group by plt_no
)
loop
if cur_r.v_qty > 0 then
update plt_result r set
r.qty = cur_r.v_qty
where r.plt_no = cur_r.plt_no;
end if;
end loop;
end;
The second one accepts PLT_NO as a parameter:
create or replace procedure update_qty
(par_plt_no in prod_result.plt_no%type)
is
v_qty number;
begin
select count(p.slab_no)
into v_qty
from prod_result p
where p.plt_no = par_plt_no;
if v_qty > 0 then
update plt_result r set
r.qty = v_qty
where r.plt_no = par_plt_no;
end if;
end;
Something like the following, where you actually open and fetch from the cursor. You'll have to assign a value to v_plt_no for the cursor to fetch anything.
create or replace PROCEDURE update_qty
is
v_plt_no nvarchar2(20);
v_qty number;
cursor q1 is
select count(slab_no)
into v_qty
from prod_result
where plt_no = v_plt_no;
begin
OPEN q1;
FETCH q1 INTO v_qty;
CLOSE q1;
if v_qty > 0 then
update plt_result
set qty = 'v_qty'
where plt_no = v_plt_no;
end if;
end;

I want to create trigger but I dont know how to do that. Below is the sample

I want to create trigger but I don't know how to do that. Below is the sample:
CREATE OR REPLACE TRIGGER checkDuration
after UPDATE on comm_shipping
FOR EACH ROW
DECLARE
quantity NUMBER;
BEGIN
SELECT * FROM comm_orders c
WHERE C.ORDER_ID = :new.order_id
AND c.quantity = 1;
IF quantity=NULL THEN
RAISE_APPLICATION_ERROR('no more items');
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN
NULL;
END;
Try the following ( I suppose your DBMS is Oracle or DB2 because of RAISE_APPLICATION_ERROR ):
CREATE OR REPLACE TRIGGER checkDuration
AFTER UPDATE ON comm_shipping
FOR EACH ROW
DECLARE
quantity NUMBER;
BEGIN
SELECT c.quantity
INTO quantity -- this part is missing
FROM comm_orders c
WHERE c.order_id = :new.order_id;
IF quantity is NULL THEN
RAISE_APPLICATION_ERROR(-20001,'no more items'); -- you need a code
-- between -20000 and -20999
END IF;
EXCEPTION WHEN NO_DATA_FOUND THEN NULL;
END;

Trigger compilation error

I need some help in creating a trigger.
create or replace trigger trigger_one
before insert on Funtom_timesheet
for each row
Declare
V_id number;
V_hours number;
Begin
Select max(timesheet_ID)+1 into v_id from Funtom_timesheet
:new.timesheet_ID :=v_id;
select grade_hours into V_hours
from funtom_grade join funtom_employee
on emp_grade = grade_id
where empid = :new.timesheet_emp;
if V_hours >:new.timesheet_hours
else
:new.timesheet_overtime :=
:new.timesheet_hours-V_hours
:new.timesheet_hours:= V_hours;
END IF;
END;
/
please tell me which part of my code is wrong so I could work on it,
Thanks
You have many syntax errors - missing ; and then. There can't be if only with else part and without expression on it.
CREATE OR REPLACE TRIGGER TRIGGER_ONE
BEFORE INSERT ON FUNTOM_TIMESHEET
FOR EACH ROW
DECLARE
V_ID NUMBER;
V_HOURS NUMBER;
BEGIN
SELECT MAX(TIMESHEET_ID) + 1 INTO V_ID FROM FUNTOM_TIMESHEET;
:NEW.TIMESHEET_ID := V_ID;
SELECT GRADE_HOURS
INTO V_HOURS
FROM FUNTOM_GRADE
JOIN FUNTOM_EMPLOYEE
ON EMP_GRADE = GRADE_ID
WHERE EMPID = :NEW.TIMESHEET_EMP;
IF V_HOURS > :NEW.TIMESHEET_HOURS THEN
NULL;
ELSE
:NEW.TIMESHEET_OVERTIME := :NEW.TIMESHEET_HOURS - V_HOURS;
:NEW.TIMESHEET_HOURS := V_HOURS;
END IF;
END;
/
Also better use SEQUENCES instead of:
SELECT MAX(TIMESHEET_ID) + 1 INTO V_ID FROM FUNTOM_TIMESHEET;
:NEW.TIMESHEET_ID := V_ID;
When selecting form the same table as inserting, you can get MUTATING trigger error (http://www.dba-oracle.com/t_avoiding_mutating_table_error.htm)

Stored Procedure two exception select statements

I am having some trouble with my Stored Procedure in Oracle 12.1
The blow code is getting an error and I think it has to do with using two EXCEPTION statements in a row?
I am created a stored Procedure for a fake small online DVD company that updates the queue position in the rental queue table. I use an IF statement that says if the member already has this DVD in the queue, then updates the queue position. In order to check if the member already has a DVD in the queue I write an SQL Select statement that checks for the DVD in the members queue. If the statement finds a DVD then it inserts it into "dvd_check". If no DVD is found then i place DVD_check to equal 0.
I also have a 2nd SQL statement to determine the original queue order of the row that is about to be updated. Both Statements run great on their own within the stored procedure but when I put them together in the StoredProcedure before my IF statement, then I get an error:
Error(17,5): PLS-00103: Encountered the symbol "EXCEPTION" when expecting one of the following: ( begin case declare end exit for goto if loop mod null...
AND
Error(29,4): PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following: end not pragma final instantiable order overriding static...
Here is my Code:
CREATE OR REPLACE PROCEDURE sp_queueorder (
dvdid_sp number,
memberid_sp number,
queueposition_sp number)
IS
dvd_check number;
old_queueposition number;
BEGIN
SELECT dvdid INTO dvd_check FROM rentalqueue
WHERE DVDid = dvdid_sp and memberid = memberid_sp;
EXCEPTION
WHEN no_data_found THEN dvd_check := 0;
SELECT queueposition INTO old_queueposition FROM rentalqueue
WHERE DVDid = dvdid_sp and memberid = memberid_sp;
EXCEPTION
WHEN no_data_found THEN old_queueposition := 0;
IF dvd_check > 0 THEN
UPDATE rentalqueue SET queueposition = queueposition + 1
WHERE memberid = memberid_sp and queueposition >= queueposition_sp AND queueposition <= old_queueposition;
UPDATE rentalqueue SET queueposition = queueposition_sp
WHERE dvdid = dvdid_sp AND memberid = memberid_sp;
END IF;
END;
Thanks so much for helping me solve this issue.
CREATE OR REPLACE PROCEDURE sp_queueorder (
dvdid_sp number,
memberid_sp number,
queueposition_sp number)
IS
dvd_check number;
old_queueposition number;
BEGIN
-- 1st select
BEGIN
SELECT dvdid INTO dvd_check FROM rentalqueue
WHERE DVDid = dvdid_sp and memberid = memberid_sp;
EXCEPTION
WHEN no_data_found THEN dvd_check := 0;
END;
-- 2nd select
BEGIN
SELECT queueposition INTO old_queueposition FROM rentalqueue
WHERE DVDid = dvdid_sp and memberid = memberid_sp;
EXCEPTION
WHEN no_data_found THEN old_queueposition := 0;
END;
IF dvd_check > 0 THEN
UPDATE rentalqueue SET queueposition = queueposition + 1
WHERE memberid = memberid_sp and queueposition >= queueposition_sp AND queueposition <= old_queueposition;
UPDATE rentalqueue SET queueposition = queueposition_sp
WHERE dvdid = dvdid_sp AND memberid = memberid_sp;
COMMIT; -- if is not needed remove
END IF;
END;
There is a missing END; in your code. Depending on how control is supposed to flow it might be supposed to look like this:
CREATE OR REPLACE PROCEDURE sp_queueorder (
dvdid_sp number,
memberid_sp number,
queueposition_sp number)
IS
dvd_check number;
old_queueposition number;
BEGIN
SELECT dvdid INTO dvd_check FROM rentalqueue
WHERE DVDid = dvdid_sp and memberid = memberid_sp;
EXCEPTION
WHEN no_data_found THEN dvd_check := 0;
---add an END; to the block here?
END;
SELECT queueposition INTO old_queueposition FROM rentalqueue
WHERE DVDid = dvdid_sp and memberid = memberid_sp;
EXCEPTION
WHEN no_data_found THEN old_queueposition := 0;
----or add an end here?
END;
IF dvd_check > 0 THEN
UPDATE rentalqueue SET queueposition = queueposition + 1
WHERE memberid = memberid_sp and queueposition >= queueposition_sp AND queueposition <= old_queueposition;
UPDATE rentalqueue SET queueposition = queueposition_sp
WHERE dvdid = dvdid_sp AND memberid = memberid_sp;
END IF;
END;
--or add it here?
END;
You have exceptions in the middle of the code. You must structure your code to look like this:
begin
begin
select ...
exception
when no_data_found ..
end;
begin
select ...
exception
when no_data_found ..
end;
...
end;