I have a procedure that is bringing up the error 'PL/SQL: Statement ignored'. This message is a little vague and I cant figure out why my procedure won't compile. All the procedure should do is check if the customer's delivery date is less then the SYSDATE and if it is delete and if not print 'customer can't be deleted'.
The code for the procedure is here:
CREATE PROCEDURE remove_customer (customer_id VARCHAR2) IS
declare
ordersCount pls_integer;
BEGIN
select count(*) into ordersCount
from placed_orders
where fk1_customer_id = remove_customer.customer_id
and delivery_date < sysdate;
if ordersCount = 0 then
THEN
DELETE FROM order_line
WHERE order_line.FK1_order_id in
(SELECT order_id FROM placed_order
WHERE placed_order.FK1_customer_id = remove_customer.customer_id
);
DELETE FROM placed_order
WHERE placed_order.FK1_customer_id = remove_customer.customer_id;
DELETE FROM customer
WHERE customer.customer_id = remove_customer.customer_id;
total_customers := total_customers - 1;
ELSE
DBMS_OUTPUT.PUT_LINE 'Customer currently has a order been delivered';
END IF;
END;
And the error message is specifying PLS-00103: Encountered the symbol "DECLARE"
thanks for any advice.
This line:
IF placed_order.delivery_date < SYSDATE
doesn't make much sense - you cannot use a column like this (think about it: which of the rows in placed_order should be compared to SYSDATE? One? All?).
If you want to check whether this customer has a delivery that's already been delivered, you need an additional SELECT:
CREATE PROCEDURE remove_customer (customer_id VARCHAR2) IS
ordersCount pls_integer;
begin
select count(*) into ordersCount
from placed_orders
where fk1_customer_id = remove_customer.customer_id
and delivery_date < sysdate;
if ordersCount = 0 then
-- your code for deleting the customer here
else
-- raise error, show message, ...
end if;
Related
I change my executable part as,
BEGIN
proc_ref_value(orders_id);
proc_display_firstname(custId);
DBMS_OUTPUT.PUT_LINE(orders_id||' '||status||' '||re_value||' '||cust_last_name );
END;
When I run It, I got output without customer full name.
Statement processed.
10101 completed 0 10102 cancelled 0 10103 completed 0
10104 completed 0 10105 refunded 740
But I want to get customer full name from first procedure.
This might be starting point based on what it seems you're trying to do with your code. You don't need procedures within your anonymous block, just cursors. Adjust variable types as you need.
DECLARE
orders_id CHAR(5);
status VARCHAR(10);
re_value NUMBER;
custId customer.customer_id%TYPE;
or_status orders.order_status%TYPE;
total orders.total_order%TYPE;
v_order_id orders.order_id%TYPE;
ref_value NUMBER;
customer_name varchar2(20);
CURSOR c1 IS
SELECT INITCAP(CONCAT(CONCAT(cust_first_name,' '),cust_last_name)) as cust_name
FROM customer
WHERE customer_id = cust_id;
CURSOR c2 IS
SELECT order_id
, order_status
, total_order
, CASE WHEN order_status='refunded' THEN total_order*0.25
WHEN order_status='completed' THEN total_order* 0
WHEN order_status='cancelled' THEN total_order*0
END order_value
FROM orders
where order_id = v_order_id;
BEGIN
v_order_id := 1; -- your value here
for x in c2 loop
or_status := x.order_status;
total := x.total_order;
ref_value := x.order_value;
for y in c1 loop
customer_name := y.cust_name;
end loop;
DBMS_OUTPUT.PUT_LINE(v_order_id||' '||or_status||' '||ref_value||' '||customer_name);
end loop;
END;
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)
I'm facing some problem here, when the customer did not make payment in 60 days. The trigger will UPDATE the customer table and still RAISE the
error -20003.
What I've realize is that the update function will be canceled if the raise exception takes place.
Is there any way to go around doing this?
CREATE OR REPLACE TRIGGER cut_supply
BEFORE INSERT ON reading
FOR EACH ROW
DECLARE
cust_ID BILL.custID%TYPE;
sent_date BILL.sentDate%TYPE;
payment_date BILL.paymentdate%TYPE;
bad_Status CUSTOMER.badStatus%TYPE;
first_name CUSTOMER.firstName%TYPE;
last_name CUSTOMER.lastName%TYPE;
NRIC_No CUSTOMER.NRIC%TYPE;
pRate_ID CUSTOMER.pRateID%TYPE;
no_new_reading EXCEPTION;
CURSOR cust_cursor IS
SELECT b.custID, b.sentDate, b.paymentDate, c.badStatus, c.firstName, c.lastName, c.NRIC, c.pRateID
FROM bill b, customer c, reading r
WHERE (sysdate - sentDate) > 20
AND paymentDate is null
AND b.custID = c.custID
AND r.readingID = b.readingID
FOR UPDATE OF c.badStatus;
BEGIN
OPEN cust_cursor;
LOOP
FETCH cust_cursor INTO cust_ID, sent_date, payment_date,
bad_Status, first_name, last_name, NRIC_No, pRate_ID;
IF cust_cursor%NOTFOUND THEN
EXIT;
END IF;
IF cust_cursor%ROWCOUNT = 0 THEN
DBMS_OUTPUT.PUT_LINE( 'No customer found');
ELSE
UPDATE customer
SET pRateID= 801, badStatus='Non Payment'
WHERE CURRENT OF cust_cursor;
RAISE no_new_reading;
END IF;
END LOOP;
CLOSE cust_cursor;
COMMIT;
EXCEPTION
WHEN no_new_reading THEN
RAISE_APPLICATION_ERROR ( -20003,
'Customer ' || first_name||''||last_Name ||
' water supply has been cut off' );
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLERRM);
END;
/
this can be solve in the following manner, create a procedure to update the customer table
create or replace procedure update_customer
as
pragma autonomous_transaction;
begin
update customer c set c.badStatus='Non Payment', c.pRateID=801
where c.custID=
(
select distinct c.custID
FROM bill b, reading r
WHERE (sysdate - sentDate) > 20
AND paymentDate is null
AND b.custID = c.custID
AND r.readingID = b.readingID
);
commit;
end;
/
Use a trigger to call the procedure itself.
CREATE OR REPLACE TRIGGER cut_supply
BEFORE INSERT ON reading
FOR EACH ROW
DECLARE
cust_ID BILL.custID%TYPE;
sent_date BILL.sentDate%TYPE;
payment_date BILL.paymentdate%TYPE;
bad_Status CUSTOMER.badStatus%TYPE;
first_name CUSTOMER.firstName%TYPE;
last_name CUSTOMER.lastName%TYPE;
NRIC_No CUSTOMER.NRIC%TYPE;
reject_new_reading_excep EXCEPTION;
CURSOR cust_cursor IS
SELECT b.custID, b.sentDate, b.paymentDate, c.badStatus, c.firstName, c.lastName, c.NRIC
FROM bill b, customer c, reading r
WHERE (sysdate - sentDate) > 20
AND paymentDate is null
AND b.custID = c.custID
AND r.readingID = b.readingID;
BEGIN
OPEN cust_cursor;
LOOP
FETCH cust_cursor INTO cust_ID, sent_date, payment_date,
bad_Status, first_name, last_name, NRIC_No;
IF cust_cursor%NOTFOUND THEN
EXIT;
END IF;
IF cust_cursor%ROWCOUNT = 0 THEN
DBMS_OUTPUT.PUT_LINE( 'No customer found');
ELSE
update_customer;
RAISE reject_new_reading_excep;
END IF;
END LOOP;
CLOSE cust_cursor;
COMMIT;
EXCEPTION
WHEN reject_new_reading_excep THEN
RAISE_APPLICATION_ERROR ( -20003,
'Customer ' || first_name||''||last_Name ||
' water supply has been cut off' );
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLERRM);
END;
/
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!
Ive currently a procedure that deletes a customer a fairly simple procedure that's inside a package body. Here is the code for the procedure that runs and deletes the customer:
PROCEDURE remove_customer (customer_id VARCHAR2) IS
BEGIN
DELETE FROM order_line
WHERE order_line.FK1_order_id in
(SELECT order_id FROM placed_order
WHERE placed_order.FK1_customer_id = remove_customer.customer_id
);
DELETE FROM placed_order
WHERE placed_order.FK1_customer_id = remove_customer.customer_id;
DELETE FROM customer
WHERE customer.customer_id = remove_customer.customer_id;
total_customers := total_customers - 1;
END;
What i want is to only delete that customer if the delivery date has past?
so there would be a if statement in the above procedure I'm just unsure how where and how to add it.
It would be along the lines of
CREATE PROCEDURE remove_customertest (customer_id VARCHAR2) IS
BEGIN
IF placed_order.delivery_date < SYSDATE
THEN
DELETE FROM order_line
WHERE order_line.FK1_order_id in
(SELECT order_id FROM placed_order
WHERE placed_order.FK1_customer_id = remove_customer.customer_id
);
DELETE FROM placed_order
WHERE placed_order.FK1_customer_id = remove_customer.customer_id;
DELETE FROM customer
WHERE customer.customer_id = remove_customer.customer_id;
ELSE
DBMS_OUTPUT.PUT_LINE ('Customer currently has a order been delivered and cant be removed.');
END IF;
END;
Does any one have any advice on this or if I'm on the right lines?
Thanks for the help I'm fairly new to PL/SQL
this condition you can add in the starting of the procedure as follow -
PROCEDURE Remove_Customer(Customer_Id VARCHAR2) IS
l_Order_Date DATE;
BEGIN
BEGIN
SELECT MAX(Delivery_Date)
INTO l_Order_Date
FROM Placed_Order
WHERE Placed_Order.Fk1_Customer_Id = Customer_Id;
EXCEPTION
WHEN OTHERS THEN
l_Order_Date := SYSDATE - 1;
END;
IF l_Order_Date < SYSDATE THEN
DELETE FROM Order_Line
WHERE Order_Line.Fk1_Order_Id IN
(SELECT Order_Id
FROM Placed_Order
WHERE Placed_Order.Fk1_Customer_Id = Customer_Id);
DELETE FROM Placed_Order
WHERE Placed_Order.Fk1_Customer_Id = Customer_Id;
DELETE FROM Customer WHERE Customer.Customer_Id = Customer_Id;
--Total_Customers := Total_Customers - 1; -- is it a global variable in the package?
ELSE
Dbms_Output.Put_Line('Customer currently has a order been delivered');
END IF;
END;