Trigger that validates line item amounts when updating a table in MySql - mysql

I am working on a lab for school which states: "Create a trigger named products_before_update that checks the new value for the discount_percent column of the Products table. This trigger should raise an appropriate error if the discount percent is greater than 100 or less than 0.
If the new discount percent is between 0 and 1, this trigger should modify the new discount percent by multiplying it by 100. That way, a discount percent of .2 becomes 20.
Test this trigger with an appropriate UPDATE statement."
My script updates the discount percent column successfully, however the "If, Then" portion does not seem to be accomplishing anything. IF I input a discount percent over 100, it does not show any errors and simply updates it. Same issue if my discount percent is less than zero. Also, if I input a number from 0-1 then it is not multiplying it by 10. Any advise would be greatly appreciated!
Here is my code:
USE my_guitar_shop;
DROP TRIGGER IF EXISTS products_before_update;
DELIMITER //
CREATE TRIGGER products_before_update
BEFORE UPDATE ON Products
FOR EACH ROW
BEGIN
DECLARE discount_percent_amount INT;
SELECT discount_percent
INTO discount_percent_amount
FROM Products
WHERE product_id = NEW.product_id;
IF discount_percent_amount > 100 THEN
SIGNAL SQLSTATE 'HY000'
set message_text =
'the discount percent cannot be greater than 100';
ELSEIF discount_percent_amount < 0 THEN
SIGNAL SQLSTATE 'HY000'
set message_text =
'the discount percent cannot be less than 0';
ELSEIF discount_percent_amount < 1 THEN
SET discount_percent_amount = (discount_percent * 10);
END IF;
END//
DELIMITER ;
UPDATE Products
SET discount_percent = .4
WHERE product_id = 3;
SELECT * FROM products;

I ended up getting it, thanks for your tip....
USE my_guitar_shop;
DROP TRIGGER IF EXISTS products_before_update;
DELIMITER //
CREATE TRIGGER products_before_update
BEFORE UPDATE ON Products
FOR EACH ROW
BEGIN
IF NEW.discount_percent > 100 THEN
SIGNAL SQLSTATE 'HY000'
set message_text =
'the discount percent cannot be greater than 100';
ELSEIF new.discount_percent < 0 THEN
SIGNAL SQLSTATE 'HY000'
set message_text =
'the discount percent cannot be less than 0';
ELSEIF NEW.discount_percent < 1 THEN
SET NEW.discount_percent = (NEW.discount_percent * 100);
END IF;
END//
DELIMITER ;
UPDATE Products
SET discount_percent = .4
WHERE product_id = 3;

Related

Logical problems in SQL procedure

I'm writing a procedure that is supposed to do the following:
Create a procedure that adds item (s) to an order.
The number of what is in stock for the item must also be reduced by the same number.
If no_of_items are more than what is in stock, the highest possible should be added so that stock is zero.
The procedure must respond with a status of how many items have been added and warn or inform if the number was not as many as desired.
If there are no items in stock, information must also be provided.
Check must also be done so that the order ID and item ID are available.
It should only be possible to add items to an order if it has shipping_status set to "open".
The procedure I have written looks as following:
DELIMITER //
CREATE PROCEDURE add_item_to_order(order_id INT, item_id INT, no_of_items INT)
BEGIN
IF order_id IN (SELECT number FROM Orders WHERE Orders.status = "open") THEN
IF item_id IN (SELECT number FROM Items WHERE Items.stock = 0) THEN
SIGNAL SQLSTATE "45000" SET MESSAGE_TEXT = "item is not in stock";
END IF;
SET #stock = (SELECT Items.stock FROM Items WHERE Items.number = item_id);
IF no_of_items <= #stock THEN
WHILE no_of_items > 0 DO
INSERT INTO orders_items (o_id, i_id) VALUES (order_id, item_id);
UPDATE Items SET Items.stock = (Items.stock - no_of_items) WHERE Items.number = item_id;
SET no_of_items = no_of_items - 1;
END WHILE;
SELECT (no_of_items) AS "Item has been added. Amount of items: " ;
END IF;
IF no_of_items > #stock THEN
WHILE no_of_items > 0 DO
INSERT INTO orders_items (o_id, i_id) VALUES (order_id, item_id - (item_id * no_of_items));
UPDATE Items SET Items.stock = (Items.stock - no_of_items) WHERE Items.number = item_id;
SET no_of_items = (no_of_items -1);
END WHILE;
SIGNAL SQLSTATE "45000" SET MESSAGE_TEXT = "Enough is not in stock. Biggest possible amount of items has been added" ;
END IF;
ELSE SIGNAL SQLSTATE "45000" SET MESSAGE_TEXT = "Order must have status Open";
END IF;
END //
DELIMITER ;
The problem is that somethings are logically wrong because the output is not as expected. If I try to call it with: CALL add_item_to_order(7, 5, 2), it should add two rows because no_of_items are 2, but it only adds one row. I need help with figuring out how I should write instead so it gives the correct output.
Also, if anyone has advice on how I can improve this query, I would very much appreciate it. I have written this procedure for a couple of days and can't figure out if its good written or bad.

How to fix Syntax Error in DATEDIFF trigger

Can anyone see what is wrong with this code?
Everything was working fine until I added the trigger to calculate the difference between two dates. First of all I altered the table just incase anyone wondered.
ALTER TABLE bookings
ADD COLUMN TheDuration varchar(10);
Then my triggers are as follows...
DELIMITER //
CREATE TRIGGER check_licence /*This trigger will approve customers with a valid licence */
BEFORE UPDATE ON customers
FOR EACH ROW
BEGIN
SET NEW.Status = CASE WHEN NEW.valid_licence = 'Yes'
THEN 'Approved'
ELSE 'Unapproved' /*So if a Customer has a valid licence, He will be automatically approved. */
/*But if he doesn't he will become unapproved[WORKING]*/
SET NEW.TheDuration = DATEDIFF(NEW.bookings.end_date, NEW.bookings.start_date) -- -- TO CALCULATE DURATION BETWEEN 2 DATES
END;
//
DELIMITER ;
The problem lays within
SET NEW.TheDuration = DATEDIFF(NEW.bookings.end_date, NEW.bookings.start_date) -- -- TO CALCULATE DURATION BETWEEN 2 DATES
As everything was working before I added this.
Same here...
DELIMITER //
CREATE TRIGGER Carperperson /* This Trigger Blocks a customer from renting two cars on the same name twice on one day. */
BEFORE INSERT ON bookings /*E.g. Mr.ABC cannot rent a Ford and a Nissan on the same day. Has to return first car first.[WORKING]*/
FOR EACH ROW
BEGIN
IF EXISTS (
SELECT 1
FROM bookings
WHERE NEW.customer_id = bookings.customer_id
AND ((new.start_date >= bookings.start_date
and new.start_date < bookings.end_date)
or (new.end_date > bookings.start_date
and new.end_date < bookings.end_date))
) THEN
SIGNAL SQLSTATE '45000'
set message_text='You can only book one car per single customer a day!' ; /* This triggers only allows to rent a car for 7 days, not more, not less[WORKING]*/
END IF;
IF ( NEW.end_date > NEW.start_date + INTERVAL 7 DAY ) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = '7 is the maximum. Please choose an earlier date.'; /*The end_date is more than seven days after start_date*/
END IF;
SET NEW.TheDuration = DATEDIFF(NEW.bookings.end_date, NEW.bookings.start_date) -- -- TO CALCULATE DURATION BETWEEN 2 DATES
END;
//
DELIMITER ;
Problem lays within...
SET NEW.TheDuration = DATEDIFF(NEW.bookings.end_date, NEW.bookings.start_date) -- -- TO CALCULATE DURATION BETWEEN 2 DATES

generated column with condition sql

mysql command to generate a column from other column according to condition
loan_amount | installment | start_date | status
------------------------------------------------------------------
500 | 100 | 2018-1-1 |
if (loan_amount % installment != 0) then month_required to pay = loan_amount / installment + 1
else month_required = loan_amount / installment;
then i want to check by adding month_required to start_date if it has crossed current date. If not then status would generate "incomplete" else "complete" .
delimiter //
set #month = "0";
create trigger `status_check` before insert on `loan`
for each row
begin
if NEW.loan_amount% NEW.installment != 0
then set #month NEW.loan_amount/ NEW.installment +1;
else set #month = NEW.loan_amount/NEW.installment;
end if ;
if NOW() <= dateadd(NEW.start_date,INTERVAL #month MONTH)
then set NEW.status = "incomplete";
else set NEW.status = "complete";
end if;
end;
//
DELIMITER ;
what is the error here? please help.
I Can't make the real answer as you don't provide all your database field nor a data sample, but some BEFORE INSERT and BEFORE UPDATE Trigger will probably do the job.
This is the base for the BEFORE INSERT :
DELIMITER //
DROP TRIGGER IF EXISTS `trg_test_insert`;
//
CREATE TRIGGER `trg_test_insert`
BEFORE INSERT ON `table`
FOR EACH ROW
BEGIN
IF NEW.loan_amount % NEW.installment != 0 THEN
SET NEW.month_required = NEW.loan_amount / NEW.installment + 1;
ELSE
SET NEW.month_required = NEW.loan_amount / NEW.installment;
END IF;
END;
//
DELIMITER ;
Take a look at MySQL 5.7 Reference Manual / ... / Trigger Syntax and Examples
And at :
MYSQL Triggers - how to store the result of a calculated field

set maximum limits in mysql sql database

I have 2 tables. Concerts / Tickets
I want to set Concert 1 to have maximum of 100 tickets and Concert 2 to have maximum of 200 tickets. so like have a concert_id be linked with a maximum number of ticket_id.
How can I do this in mysql? thanks
You can write triggers:
delimiter //
drop trigger if exists limitInsertsTrigger //
create trigger limitInsertsTrigger before insert on tickets
for each row
begin
declare msg varchar(128);
if (select count(*) from tickets where concert_id = new.concert_id)>
(select max_tickets_number from concert where id=new.concert_id)
then
set msg = concat('MyTriggerError: Trying to insert too many tickets');
signal sqlstate '45000' set message_text = msg;
end if;
end //
Remember to have a max_tickets_number column in the concert table.

MYSQL trigger with if statements

I can't seem to make this trigger work.
CREATE TRIGGER class_check BEFORE INSERT ON Category
DECLARE x VARCHAR(1);
SET x = (SELECT Type1 FROM Category);
IF (x<>'A') THEN
CALL `'ERROR'`;
END IF;
IF (NEW.MxLen > 3 AND x ='M') THEN
CALL `'ERROR LENGTH MUST BE LESS THAN 3 FOR M CLASS LICENSE'`;
ELSEIF (NEW.MxLen > 5 AND x ='G') THEN
CALL `'ERROR LENGTH MUST BE LESS THAN 5 FOR G CLASS LICENSE'`;
ELSEIF (NEW.MxLen > 30) THEN
CALL `'ERROR LENGTH MUST BE LESS THAN 30 FOR A,B,C,D,E CLASS LICENSE'`;
END IF;
The trigger above doesn't work the way i want it to and I can't seem to find the problem.
Basically, I want it to check if the type1 in the Category table is Not A then shoot an error. Everytime I try to add A, it will still shoot the error.
Any help would be appreciated. I have the same for BEFORE UPDATE as well.
The backticks are escaping the name of whatever is between them, saying that it is an identifier. I doubt that you actually have any identifiers with these names. Just use the single quotes for the strings:
Normally, call would have stored procedure name after it. I am guessing that you really want signal to raise an error:
CREATE TRIGGER class_check BEFORE INSERT ON Category
DECLARE x VARCHAR(1);
SET x = (SELECT Type1 FROM Category);
IF (x <> 'A') THEN
SIGNAL '45000' SET MESSAGE_TEXT = 'ERROR';
END IF;
IF (NEW.MxLen > 3 AND x ='M') THEN
SIGNAL '45000' SET MESSAGE_TEXT = 'ERROR LENGTH MUST BE LESS THAN 3 FOR M CLASS LICENSE';
ELSEIF (NEW.MxLen > 5 AND x ='G') THEN
SIGNAL '45000' SET MESSAGE_TEXT = 'ERROR LENGTH MUST BE LESS THAN 5 FOR G CLASS LICENSE';
ELSEIF (NEW.MxLen > 30) THEN
SIGNAL '45000' SET MESSAGE_TEXT = 'ERROR LENGTH MUST BE LESS THAN 30 FOR A,B,C,D,E CLASS LICENSE';
END IF;
Also, it is not clear what this line does:
SET x = (SELECT Type1 FROM Category);
It is likely to return an error if more than one row is in Category.