MySQL write a trigger to prevent from buying too much - mysql

I have a table warehouse where I have information about articles in my store (article id as foreign key and quantity). Then, I have another table, shoppinglist where I have a clients id, article id and quantity. Lets say, that client wants to buy 3 articles but theres only one article available. How to write a trigger which help me to prevent from buying too much?
I tried this:
DELIMITER $$ CREATE TRIGGER check BEFORE INSERT ON shoppinglist FOR EACH ROW BEGIN IF warehouse.quantity < shoppinglist.quantity THEN CALL fail('You cant buy that much'); END IF; END $$ DELIMITER;
but this seems not to work. I mean, when I do:
INSERT INTO shoppinlist (clients_id, article_id, quantity) VALUES (1, 2, 100);
having only 2 articles with id = 2 on warehouse its ok, its possible. What did I do wrong?

What specific article would warehouse.quantity or shoppingList.quantity refer to in your code?
Also, check is a reserved keyword.
Try this:
DELIMITER $$
CREATE TRIGGER qtyCheck BEFORE INSERT ON shoppinglist
FOR EACH ROW
BEGIN
SET #qty = (SELECT quantity FROM warehouse WHERE article_id = NEW.article_id);
IF #qty < NEW.quantity THEN
CALL fail('You cant buy that much');
END IF;
END $$
DELIMITER ;
Note that I renamed the trigger, I'm guessing the name of the article_id column on the warehouse table, I used the NEW variable instead of shoppingList within the body of the trigger, and you need a space before the semicolon in DELIMITER ;, though this might've been a typo when posting.
Finally, you may get the following error if the fail function isn't defined. It doesn't exist on my system...
ERROR 1305: PROCEDURE testing.fail does not exist

Related

How do I create a trigger in MariaDB? Currently my attempt causes the console to be stuck

I have the following tables:
Fruits
Fruit Table Image
Pair
Pair Table Image
Basically I would like to create a trigger, that when I insert a new fruit that has a sweetness of 5, I would like the rest of the fruits to have their ids paired with this newly inserted fruit added to the pair table.
So example if I were to issue the command, Insert into Fruits values (1006, 'Kiwi', 5);
I would expect the Pair table to be updated as follows,
Updated Pair Table
I tried to create a trigger with the following code,
Delimiter //
CREATE TRIGGER t1 AFTER INSERT ON fruits
FOR EACH ROW
BEGIN
IF (sweetness.new=5) THEN
INSERT into Pair values(id.old,id.new);
END IF;
END//
Delimiter;
However, after I tried the above code, my MariaDB console application seems to be stuck, whenever i press enter the -> arrows keep appearing.
Stuck error
Any kind soul in the universe Please help!
You could
Delimiter //
CREATE TRIGGER t AFTER INSERT ON fruits
FOR EACH ROW
BEGIN
IF (new.sweetness=5) THEN
INSERT into Pair
SELECT DISTINCT ID,NEW.ID
FROM FRUITS
where id <> new.id
;
END IF;
END //
DELIMITER ;
Note the space between the end and the delimiter.

MySQL TRIGGER to INSERT BEFORE INSERT using SELECT, IF, etc

I am trying to write a trigger that combines an insert & select, I've found numerous topics online, but, none seem to relate to my exact problem, maybe I am missing something with my structure?
The aim of this is that on the event of a cancellation in our audit log, then I define a cancellation reason based on a series of business logic in another table, this logic is drawn together in a SELECT using CASE & subqueries.
I want to expand the following trigger that currently works and replace the SET cancellation_point='test' element with the SELECT query I just mentioned.
DELIMITER $$
CREATE
TRIGGER `cancellation_stage` BEFORE INSERT ON `log`
FOR EACH ROW
BEGIN
IF (NEW.status='cancel' AND NEW.type='0') THEN
INSERT INTO cancellation_stage
SET
id=NEW.id,
property_id=NEW.entity_id,
cancellation_date=NOW(),
cancellation_point='test';
END IF;
END;
$$
DELIMITER ;
I did try to construct this myself using various guidance from here, but, its just not working. I got this code to physically save as a trigger, but, it did not populate the data in the database (I have replaced my SELECT with a basic query example below):
DELIMITER $$
CREATE
TRIGGER `cancellation_stage` BEFORE INSERT ON `log`
FOR EACH ROW
BEGIN
DECLARE cancellation_point VARCHAR(255);
SET cancellation_point = ( SELECT * FROM x);
IF (NEW.transition='cancel' AND NEW.entity_type='property') THEN
INSERT INTO cancellation_stage
SET
id=NEW.id,
property_id=NEW.entity_id,
cancellation_date=NOW(),
cancellation_point=NEW.cancellation_point;
END IF;
END;
$$
DELIMITER ;
Any help would be greatly appreciated :)

Can't Setup MySQL Trigger To INSERT Into Second Table

I have two tables which I use to store call details in. One table (Call_Detail) stores the header details against each call that gets entered, the second (Call_History) stores every comment against the call. So a single call will only appear ONCE in the Call_Detail table, but may appear multiple times in the Call_History table.
I currently run a Query to return the latest comment against a group of calls. So, I return the header details out of Call_Detail and then cross reference against the Call_History to find the 'newest' comment (thanks to some outside help). However, this Query can be quite time consuming when running against a large number of calls.
Therefore, I'm thinking to optimize my Query, I want to setup a trigger that records these details.
I am wanting to catch any INSERT command into the Call_History table and record the comment and date/time into the Call_Detail table against the relevant call ID.
So far I have the following but it doesn't like my syntax for some reason:
DELIMITER $$
CREATE TRIGGER Last_Call_Update
AFTER INSERT ON call_history
FOR EACH ROW
BEGIN
UPDATE call_detail
SET last_updated = NEW.updated_at, last_commment = NEW.body
WHERE id = NEW.ticket_id
END $$
DELIMITER ;
Add semicolon after UPDATE statement
DELIMITER $$
CREATE TRIGGER Last_Call_Update
AFTER INSERT ON call_history
FOR EACH ROW
BEGIN
UPDATE call_detail
SET last_updated = NEW.updated_at, last_commment = NEW.body
WHERE id = NEW.ticket_id;
END $$
DELIMITER ;

mySQL trigger - What is wrong with my syntax?

I need to write a trigger where if a customerName of an incoming enquiry matches a customer name in a synonymns table then the customerID from that table is used to find the customer in the customer table.
I got a trigger to work which just searched the customer table but not the synonym table first. I was thinking something like: (It's psuedo-esque code)
CREATE TRIGGER `Find Customer` AFTER INSERT ON `enquiry` FOR EACH ROW
BEGIN
INSERT INTO customersmatched (enquiryID, customerID)
SELECT NEW.id, id, customerName, customerID FROM customer, customerSynonyms WHERE
customerSynonyms.customerName = NEW.companyName AND customer.id = customerSynonyms.customerID
HAVING COUNT(id)=1
END;
The error I recieve:
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'END' at line 7
But I'm afriad this doesn't work.
Any idea how one would go about this in mySQL? Thanks!
UPDATE
I tried this way too - it didn't work either!
DELIMITER $$
CREATE TRIGGER Find_Customer AFTER INSERT ON enquiry
FOR EACH ROW
BEGIN
IF EXISTS (SELECT customerID FROM customerSynonyms WHERE customerName = NEW.companyName) THEN
IF EXISTS (SELECT id FROM customer WHERE id = #customerID) THEN
INSERT INTO customersMatched (enquiryID, customerID)
HAVING COUNT(id)=1
END IF;
END IF;
END$$
DELIMITER ;
Update 2
It turns out I was WAYYY over complicating things. The customerSynonym table had the customerID stored in a column, which was all I really needed as I could just grab all the data through php with the customerID. The final trigger which works was super simple:
INSERT INTO customersmatched (enquiryID, customerID)
SELECT NEW.id, customerID FROM customersynonyms WHERE
customersynonyms.customerName=NEW.companyName
HAVING COUNT(id)=1
Thanks for all your answers, they're always very much appreciated! :-)
I think you want something like this:
CREATE TRIGGER Find_Customer AFTER INSERT ON enquiry FOR EACH ROW
BEGIN
INSERT INTO customersmatched (enquiryID, customerID)
SELECT NEW.id, customerID FROM customer, customerSynonyms
WHERE customerSynonyms.customerName = NEW.companyName
AND customer.id = customerSynonyms.customerID
HAVING COUNT(id)=1
END;
A few things to note:
I renamed the trigger to Find_Customer. I'm not 100% sure if you can have a space in the trigger name
I removed the single quotes around Find_Customer and enquiry. The single quotes could be read as a string literal by mysql and cause problems. It's better to avoid that if possible.
I changed your select query to only select NEW.id and customerID, since those are the only two things you're inserting. You might have to play with the select a little bit more to get it exactly how you want it.
If this is just part of the trigger, and you have more than just a one-statement trigger, you'll need to set delimiters. Basically, you'd have delimiter | before the trigger definition, and then END| instead of END
Good luck!

MySQL Trigger Creation. What's wrong with my trigger?

I'm trying to create a trigger, however I keep getting back a syntax error.
Here's the statement:
DELIMITER $$
CREATE TRIGGER `swtalentbank`.`after_candidate_insert`
AFTER INSERT ON `Candidates` FOR EACH ROW
BEGIN
INSERT INTO useradmin (username, talent)
VALUES (NEW.email, 1);
UPDATE `Candidates` SET UserID = useradmin.userid where useradmin.username = NEW.email;
END
DELIMITER ;
I have a registration form on my site. When a person registers it populates the Candidates table with their profile information.
In the Candidates table, there are various fields, two of them being 'email' and 'UserID'.
UserID is also the PK in 'useradmin', so I'm linking the two up.
So when a user registers, I need to insert a record into 'useradmin' with the email address that's just been used to register, and then update the 'Candidates' table, with UserID that's just been created in 'useradmin'.
I hope this makes sense?
NB. I am changing the delimiter before running the statement.
Besides properly using DELIMITER when creating a trigger you have at least two fundamental issues with your current code:
In MySQL you can't use issue a DML statement (in your case UPDATE) against a table (candidates) on which you defined a trigger (also candidates). Your only option is to use BEFORE trigger and set a value of userid column of a row being inserted to a proper value.
You can't arbitrarily reference a column (useradmin.userid) of a table out of the context like you did in your UPDATE. You didn't joined useradmin table or used it in a subquery.
That being said and assuming that userid in useradmin table is an auto_increment column your trigger might look like this
DELIMITER $$
CREATE TRIGGER after_candidate_insert
BEFORE INSERT ON candidates
FOR EACH ROW
BEGIN
INSERT INTO useradmin (`username`, `talent`) VALUES (NEW.email, 1);
SET NEW.userid = LAST_INSERT_ID();
END$$
DELIMITER ;
Here is SQLFiddle demo
You should use semicolon after end your insert query.
You can use INSERT ... ON DUPLICATE KEY UPDATE syntax for your purpose
try out this...
DELIMITER $$
CREATE TRIGGER `swtalentbank`.`after_candidate_insert`
AFTER INSERT ON `Candidates` FOR EACH ROW
BEGIN
INSERT INTO useradmin (username, talent)
VALUES (NEW.email, 1);
UPDATE `Candidates` SET UserID = useradmin.userid where useradmin.username = NEW.email;
END $$
DELIMITER ;