Logical problems in SQL procedure - mysql

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.

Related

Creating Stored Procedures and joining tables

I am using a database called salesshort used mostly for learning MySQL. I am trying to create a stored procedure but for some odd reason when I run my code is not even creating the store procedure I think my syntax is wrong.
here are the instructions and my code.
Create a stored procedure ‘gbSaleP’ that returns the following ‘order types’:
"we are loosing money" if the actual profit for each order (i.e., OrderNumber)- is lower than or equal to zero; "good sale" if the difference between potential profit and actual profit is $2500 or lower; and
"bad sale" if the difference between potential profit and actual profit is greater than $2500.
delimiter //
create procedure gbSaleP ( in orderNumber int(10), out SaleStatus varchar (40))
begin
set gbsaleP = (select sum(o.quantityOrdered*p.MSRP - o.quantityOrdered*p.buyPrice) - abs(sum(o.quantityOrdered*o.priceEach - o.quantityOrdered*p.buyPrice))
from orderdetails as o
join products as p
using(productCode)
group by orderNumber
having porderNumber = orderName);
if gbSaleP <= 2500 then set SalesStatus = "good sale"
elseif gbSaleP => 2500 then set SaleStatus = "bad sale"
else set gbSaleP = "unknown"
end if;
end;
delimiter //
If your amount calculation script is right, you may use below.
DELIMITER //
CREATE procedure gbSaleP (IN orderNumber int(10), OUT SaleStatus varchar (40))
BEGIN
DECLARE amount DECIMAL(20,2);
set amount = (/*.......Correct SQL script*/);
if amount <= 2500 then
set SaleStatus = 'good sale';
elseif amount > 2500 then
set SaleStatus = 'bad sale';
else
set SaleStatus = 'unknown';
end if;
END; //
DELIMITER ;
You can test it with:
CALL `gbSaleP` (7, #`SaleStatus`);
SELECT #SaleStatus;

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

Set a limit occurrence for a value in a mysql table

So let's say i have a table that has a column "id_author" , i'd like to set a limit for the occurrence of the same value ; example : can't have more than 3 same "id_author" values so when i insert the 4th one it's refused.
Is there a way to implement this? Thanks
You can use a trigger before insert, that will throw a signal in case it violates your condition:
CREATE TRIGGER tooManyRecords
BEFORE INSERT ON yourTable
FOR EACH ROW
BEGIN
DECLARE counter INTEGER;
SELECT COUNT(*) INTO counter FROM yourTable
WHERE id_author = NEW.id_author;
IF counter >= 3 THEN
SIGNAL SQLSTATE '45000' SET message_text = 'there are already 3 records for the provided id';
END

trigger mysql unknown table

I've been trying to solve this problem. Here is the code:
CREATE TRIGGER some_trigger AFTER UPDATE ON table_a
FOR EACH ROW BEGIN
DECLARE tname VARCHAR(20);
IF (table_a.field_offer=1) THEN
SET tname='table_b';
ELSEIF (table_a.field_offer=0) THEN
SET tname='table_c';
END IF;
IF ((new.field_state = 0)) THEN
UPDATE tname join table_a on tname.ID=table_a.ref_field
SET tname.STOCK = tname.STOCK -1;
ELSEIF ((new.field_state = 1)) THEN
UPDATE tname join table_a on tname.ID=table_a.ref_field
SET tname.STOCK = tname.STOCK +1;
END IF;
END;
I am getting:
Unknown table 'table_a' in field list. Field_offer and field_state can
be null.
I've shown below what was said in the comments to the question:
CREATE TRIGGER some_trigger AFTER UPDATE ON table_a
FOR EACH ROW BEGIN
DECLARE tname VARCHAR(20);
IF (NEW.field_offer=1) THEN
UPDATE `table_b`
SET STOCK = CASE NEW.field_state
WHEN 0 THEN STOCK - 1
WHEN 1 THEN STOCK + 1
ELSE STOCK
END
WHERE ID=NEW.ref_field
;
ELSEIF (NEW.field_offer=0) THEN
UPDATE `table_c`
SET STOCK = CASE NEW.field_state
WHEN 0 THEN STOCK - 1
WHEN 1 THEN STOCK + 1
ELSE STOCK
END
WHERE ID=NEW.ref_field
;
END IF;
...
Note that I changed the updates from UPDATE ... JOIN as MySQL does not allow you to change the data of the triggered table; while you were not actually updating table_a, the JOIN could have been enough for MySQL to have objected... that and the joins would've updated every row in table_b/c that had a match in table_a, not just table_a rows related to the values in or row of the trigger.

Trigger that validates line item amounts when updating a table in 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;