SQL duplicate trigger - mysql

I have simple project for database classes there i have shop database which implement such logic: for each customer in order table we have order with type = 'CART' when customer confirm his order his order change it type to 'ORDER' and we create a new CART for our customer.
Now i want to write trigger that allows me to control that each customer has only one CART.
I write something like this
DELIMITER $$
USE `newshop`$$
CREATE
DEFINER=`root`#`localhost`
TRIGGER `newshop`.`cart_check`
BEFORE INSERT ON `newshop`.`order`
FOR EACH ROW
BEGIN
DECLARE msg VARCHAR(255);
DECLARE count_pn INTEGER;
SELECT count(*) INTO count_pn FROM newshop.order
where newshop.order.type = NEW.type
and NEW.user_id = newshop.order.user_id
and NEW.type = 'CART'
or NEW.type = 'cart'
LIMIT 1;
if count_pn > 0 THEN
BEGIN
set msg = 'Oh no';
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = msg;
end;
ELSE
BEGIN
set msg = 'Oh yeah';
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = msg;
END;
END IF;
END$$
then when i try to insert into table new order with type cart for user with id = 1, that already has a cart - this trigger doesn't allow me to do this and if i try to add a cart for another user, that doesn't have cart - this trigger also doesn't allow me to do this.

In else, you also have the SIGNAL SQLSTATE=45000, which is unhandled exception, it will cause return as failed.
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = msg;

Related

SIGNAL SQLSTATE '45000' Doesn't stop Insert

I am having problems implementing a trigger into my table. I am using MySQL, Phpmyadmin
Scenario: Table User(user_id, name, surname, date_of_joining), record(record_id, date_of_record, weight, height, id_user)
a user can have multiple records which show his weight and height at a certain date. id_user is a foreign key referencing to user_id.
I am trying to implement a trigger for insert and update which checks if date_of_record is greater than date_of_joining, if not, the insert should be stopped.
This is a trigger I tried and the insert still goes through
CREATE TRIGGER date_check_insert BEFORE INSERT ON record
FOR EACH ROW
BEGIN
DECLARE date_of_registering DATE;
SET date_of_registering = (SELECT date_of_registering FROM user WHERE user_id = new.id_user);
IF (new.date_of_record NOT BETWEEN date_of_registering AND CURDATE()) THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = "Can not insert that value";
END IF;
END
Any help is appreciated
I'd slightly change the trigger:
Use session variable (so no DECLARE needed)
Put comparison logic in a single place in the WHERE clause (easier to read & understand)
Shows reason in error message
Use SELECT INTO variable instead of SET variable = query (not necessary, I just prefer this way)
So:
CREATE TRIGGER date_check_insert BEFORE INSERT ON record
FOR EACH ROW
BEGIN
SET #found = NULL;
SELECT
user_id INTO #found
FROM
user
WHERE
user_id = NEW.id_user
AND NEW.date_of_record BETWEEN date_of_registering AND NOW() -- or CURDATE() depend on your datetype
;
IF #found IS NULL THEN
SET #msg = CONCAT('Can not insert. Out of range value ', NEW.date_of_record);
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = #msg;
END IF;
END

Issue handling with MySQL trigger

This is my trigger for show error handling :
DELIMITER //
CREATE TRIGGER NOTA_PENJUALAN_INS BEFORE INSERT ON nota_penjualan FOR EACH ROW
BEGIN
DECLARE VDATE DATETIME;
If (NEW.INVENTORY_OUT_ID IS NOT NULL) then
CALL STATUS_INV_OUT(NEW.INVENTORY_OUT_ID);
SELECT (a.DOCUMENT_DATE) INTO VDATE
FROM inventory_out a
INNER JOIN NOTA_PENJUALAN b ON a.INVENTORY_OUT_ID=b.INVENTORY_OUT_ID
WHERE b.NOTA_PENJUALAN_ID=NEW.NOTA_PENJUALAN_ID;
End IF;
IF(VDATE > NEW.DOCUMENT_DATE) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'sorry can not exceed the date that has been specified';
END IF;
END
//
It displays:
And does not display my ShowMessage.

MySQL : Trigger Syntax not correct

I'm trying to write a trigger for a table named classes_tbl where I basically want to check before update if the participants are at the maximum, if true - do not allow update, and raise error message.
As well as check if participants = 0 in case the the update table tries to decrease the number, it needs not to be possible to decrease below 0 - and again raise an error message in this case.
I'm not 100% accustomed to MySQL so I'm not sure what is missing or wrong. It would be nice If someone could give me a hint.
Here is my Create Trigger syntax:
DELIMITER //
CREATE TRIGGER MaxBelegt_TRGGR
BEFORE UPDATE ON classes_tbl
FOR EACH ROW
BEGIN
DECLARE
n_count NUMBER(3);
msg varchar(255);
SELECT maxParticipants
INTO n_count
FROM rooms_tbl
WHERE rid = :NEW.rid;
IF :OLD.participants = n_count THEN
set msg = concat('MyTriggerError: MaxParticipants for Room exceeded. On MaxBelegt_TRGGR -> belegtAnz : ', cast(OLD.participants as char));
signal sqlstate '45000' set message_text = msg;
END IF;
IF :NEW.participants < 0 THEN
set msg = concat('MyTriggerError: Participant number already 0. On MaxBelegt_TRGGR -> belegtAnz : ', cast(OLD.participants as char));
signal sqlstate '45000' set message_text = msg;
END IF;
END
//
DELIMITER;
Thank You!
BTW: I'm using mysql version : 5.6.24 .. just in case

Can MySQL TRIGGER check all INSERT values separetly?

I've got simple database with tables: Sklep(SklepNazwa,Adres), Towar(TowarNazwa,Producent), Sprzedaz(SklepNazwa,SklepAdres,TowarNazwa,TowarProducent,Cena,Data)
I had to create TRIGGER like shown below.
Problem is that it don't work when I try to INSERT several rows at once. When at least one row triggers SIGNAL all values are dumped. Nothing gets inserted, even when it is ok to be inserted.
Can I somehow call
INSERT INTO Sprzedaz
VALUES (...),(...),(...),(...);
where some values are ok to be inserted and some should fail and show SIGNAL message?
DELIMITER $$
CREATE TRIGGER SprzedazInsert
BEFORE INSERT ON `Sprzedaz`
FOR EACH ROW
BEGIN
IF (SELECT COUNT(1) FROM Sprzedaz
WHERE NEW.SklepNazwa = Sprzedaz.SklepNazwa
AND NEW.SklepAdres = Sprzedaz.SklepAdres
AND NEW.TowarNazwa = Sprzedaz.TowarNazwa
AND NEW.TowarProducent = Sprzedaz.TowarProducent
AND NEW.Cena = Sprzedaz.Cena
AND NEW.`Data` = Sprzedaz.`Data`) > 0
THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'INSERT FAILED: Row already exists.';
ELSE
IF (SELECT COUNT(1) FROM Sklep WHERE NEW.SklepNazwa = Sklep.SklepNazwa) > 0
THEN
IF (NEW.SklepAdres != (SELECT Adres FROM Sklep WHERE NEW.SklepNazwa = Sklep.SklepNazwa))
THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'INSERT FAILED: Wrong "Sklep" data.';
END IF;
ELSE
INSERT INTO `Sklep` (`SklepNazwa`,`Adres`)
VALUES (NEW.SklepNazwa,NEW.SklepAdres);
END IF;
IF (SELECT COUNT(1) FROM Towar WHERE NEW.TowarNazwa = Towar.TowarNazwa) > 0
THEN
IF (NEW.TowarProducent != (SELECT Producent FROM Towar WHERE NEW.TowarNazwa = Towar.TowarNazwa))
THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'INSERT FAILED: Wrong "Towar" data.';
END IF;
ELSE
INSERT INTO `Towar` (`TowarNazwa`,`Producent`)
VALUES (NEW.TowarNazwa,NEW.TowarProducent);
END IF;
END IF;
END$$
If you try to insert several rows in the same transaction, the dbms assumes you want all the inserts to succeed or fail as a group. If you want rows to succeed or fail individually, you need to commit after each insert.

mySQL Triggers PRINT & ROLLBACK

DELIMITER $$
CREATE TRIGGER insertTrigger BEFORE INSERT ON `agents`
FOR EACH ROW
BEGIN
DECLARE groupID int;
SET groupID = 0;
SET groupID = (SELECT id FROM `groups` WHERE `id` = NEW.group_id);
IF (groupID != 0) THEN
PRINT 'ID is ' + groupID;
ROLLBACK;
END IF;
END$$
DELIMITER ;
The above trigger is created for checking if the foreign key ID exists in the group table.
1) How do I print error messages in mySQL?
2) ROLLBACK Function doesn't work. It gave me the following error message.
"#1422 - Explicit or implicit commit is not allowed in stored function or trigger."
You can use SIGNAL statement to raise an error with custom message from the trigger.
...
IF (groupID != 0) THEN
SET #msg = CONCAT('ID is ', groupID);
SIGNAL SQLSTATE '02000' SET MESSAGE_TEXT = #msg;
END IF;
...
If you want just warning message, then use SQLSTATE code starting with '01...'.