MYSQL trigger with if statements - mysql

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.

Related

How to limit the input value of another column according to the value entered in the column

I have a data_type table and a data table.
The column structure is as follows.
data_type data
========= ====================
id | Type Type_ID | data_count
--------- --------------------
1 | a 1 | 50
2 | b 2 | 100
3 | c 3 | 30
When I add a new row to a data table, I want to set a different limit on the number of data_ that can be input according to the type_id.
for example
In type a, only integers between 50 and 100 can be entered.
I want to be able to input 0 to 100 for type b and 10 to 30 for type c.
Is it possible to put such a limit when doing an INSERT INTO?
For reference, below is my current code.
DAO.js
const createRecordData = async (userId, a1, a2, typeId, count) => {
await myDataSource.query(
`INSERT INTO a (user_id,a1,a2)
VALUES (?,?,?)`,
[userId, a1, a2]
);
await myDataSource.query(`
DELIMITER $$
CREATE TRIGGER checkValueTBL
BEFORE INSERT ON TBL FOR EACH ROW
BEGIN
IF NEW.data_type = 1 THEN
IF NEW.datas < 10 OR NEW.datas > 90 THEN
SIGNAL SQLSTATE '45015'
SET message_text = 'Type a: value not between 10 and 90';
END IF;
ELSEIF NEW.data_type = 2 THEN
IF NEW.datas < 30 OR NEW.datas > 50 THEN
SIGNAL SQLSTATE '45015'
SET message_text = 'Type a: value not between 30 and 50';
END IF;
ELSEIF NEW.data_type = 3 THEN
IF NEW.datas < 60 OR NEW.datas > 200 THEN
SIGNAL SQLSTATE '45015'
SET message_text = 'Type a: value not between 60 and 200';
END IF;
END $$
DELIMITER ;`);
const datas = await myDataSource.query(
`INSERT INTO data (a_id,typeId,count)
VALUES ((SELECT LAST_INSERT_ID()),?,?)`,
[typeId, count]
);
return datas;
};
If you write the above, you will get the following error.
"err": "ER_PARSE_ERROR: 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 'DELIMITER $$\n CREATE TRIGGER checkValueTBL \n BEFORE INSERT ON TBL FOR EACH ROW' at line 1"
I need help.
You could do that with a BEFORE INSERT trigger (see here for a short tutorial)
DELIMITER $$
CREATE TRIGGER `checkValueTBL` BEFORE INSERT ON `TBL` FOR EACH ROW
BEGIN
IF NEW.data_type = 1 THEN
IF NEW.data_value < 10 OR NEW.data_value > 25 THEN
SIGNAL SQLSTATE '45015'
SET message_text = 'Type a: value not between 10 and 25';
END IF;
ELSEIF NEW.data_type = 2 THEN
...
ELSEIF NEW.data_type = 3 THEN
...
END IF;
END $$
DELIMITER ;
You can also retrieve the numeric value from a different table.
Inserting an out of bounds value will trigger an error (if you do that with INSERT IGNORE, the insert will silently fail, and the data will not be input.
You can also correct any value(s) if you prefer (i.e., if it is less than 10, set it to 10, if it is above 123, set it to 123, and so on): omit the SIGNAL statement and the insert will proceed with the altered values.

MySQL: how to make an attribute "nullable" only if certain condition

I am creating a table for a DB, and I would like (if possible) to do something like this:
Attribute X can be NULL if, and only if, attribute Y is "value1".
Is there a way to do this? I want to do this because I could delete an entity, reducing the complexity of my project (or at least I think I would get some advantages).
Thanks :)
In very recent versions of MySQL, you can use a check constraint for this:
create table mytable (
x int,
y int,
check(x is not null or y = 1)
)
If MySQL version is not new enough for to use CHECK constraint (below 8.0.16) then use
DELIMITER ##;
CREATE TRIGGER tr_bi_check_my_constraint
BEFORE INSERT
ON my_table
FOR EACH ROW
BEGIN
IF NEW.attribute_X IS NULL AND NEW.attribute_Y != 'value1' THEN
SIGNAL SQLSTATE 45000
SET MESSAGE_TEXT = 'Attribute X can be NULL if, and only if, attribute Y is "value1".';
END IF;
END
##;
CREATE TRIGGER tr_bu_check_my_constraint
BEFORE UPDATE
ON my_table
FOR EACH ROW
BEGIN
IF NEW.attribute_X IS NULL AND NEW.attribute_Y != 'value1' THEN
SIGNAL SQLSTATE 45000
SET MESSAGE_TEXT = 'Attribute X can be NULL if, and only if, attribute Y is "value1".';
END IF;
END
##;
DELIMITER ;

How to structure an if exists query to produce an error message

I have created a procedure which I am using to insert new columns into a table, and I have done an IF statement to basically say that if the date entered is before current date or not at least 30 days in the future then throw an error, now I want to create an IF statement that will only insert a new column if one of the rows exists... there are only three possible courses that are in the table so the procedure asks for a course code and a date, can someone push me in the right direction for how to structure my IF statement to give an error when one of the three codes are not entered?
I don't know what keywords to use.
Here is my IF statement for the date checking:
IF (give_date < DATE_ADD(CURDATE(), INTERVAL 1 MONTH)) OR (give_date <= CURDATE()) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Please Enter A Date Over One Month';
ELSEIF (WEEKDAY(give_date) = 5 )THEN SET loop_date = DATE_ADD(give_date, INTERVAL 2 DAY);
ELSEIF (WEEKDAY(give_date) = 6 )THEN SET loop_date = DATE_ADD(give_date, INTERVAL 1 DAY);
ELSE SET loop_date = give_date;
END IF;
I am trying to do something like this...
IF (new_code, EXISTS IN (module (course_code)) THEN
SIGNAL SQLSTATE '45000'SET MESSAGE_TEXT = 'Please Check Entered Course And Try Again';
END IF;
Also tried doing this but getting an error saying the subquery returns more than one row...
IF give_code != ( SELECT course_code FROM module WHERE course_code = ('WSD' OR 'DDM' OR 'NSF'))THEN
SIGNAL SQLSTATE '45000'SET MESSAGE_TEXT = 'Please Check Entered Course And Try Again'; END IF;
Got it working by doing it like this:
IF give_code NOT IN ( SELECT course_code FROM module WHERE course_code = ('WSD' OR 'DDM' OR 'NSF'))THEN
SIGNAL SQLSTATE '45000'SET MESSAGE_TEXT = 'Please Check Entered Course And Try Again'; END IF;
Does it work for you?
IF ( SELECT count(*) FROM module WHERE course_code in ('WSD','DDM','NSF')) > 0
THEN
SIGNAL SQLSTATE '45000'SET MESSAGE_TEXT = 'Please Check Entered Course And Try Again';
END IF;

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 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;