How can I prevent insertion into a table through trigger? - mysql

I've to prevent the insertion into table when the number of rows having colour as Red exceeds 100. Here's the code that i've written, just dont know what to write in the blank.
CREATE TRIGGER onRegisterInsert BEFORE INSERT ON table_name FOR EACH ROW
BEGIN
DECLARE n INT DEFAULT 0;
IF New.Colour='Red' THEN
SELECT COUNT(*) INTO n FROM table_name WHERE Colour='Red';
if n > 100 THEN
---
END IF
END IF
END
I thought of writing SIGNAL SQLSTATE '45000' to prevent insertion but i dont want to throw an error, because i'm inserting a list of data and if i throw an error the insertion of data after this will also be stopped.
I also thought of writing an after insert trigger instead of before.
DELIMITER //
CREATE TRIGGER onRegisterInsert After INSERT ON table_name FOR EACH ROW
BEGIN
IF New.Colour='Red' THEN
SELECT COUNT(*) INTO #count FROM table_name WHERE Colour='Red';
IF (#count >= 100) THEN
delete from table_name new;
END IF;
END IF;
END //
but this code too gives an error.

One thing you could do is use INSERT IGNORE in the calling app instead of INSERT.

Related

How to control column totals in mySQL using trigger?

I want to use Trigger in Mysql to be able to control "evaluation_weight" column in "evaluation_criteria" table. If the sum of the "evaluation_weight" column >= 100 after update/insert, it will not be possible to update/insert the newly entered value.
Here is the picture of "evaluation_criteria" table
You would need two triggers with one for update and another one for insert.
delimiter //
drop trigger if exists check_evaluation_insert ;
create trigger check_evaluation_insert before insert on evaluation_criteria for each row
begin
if (select ifnull(sum(evaluation_weight),0) from evaluation_criteria) + new.evaluation_weight>= 100 then
signal SQLSTATE VALUE '99999' SET MESSAGE_TEXT = 'The limit of evaluation_weight has been reached. INSERT fails. ';
end if;
end//
drop trigger if exists check_evaluation_update ;
create trigger check_evaluation_update before update on evaluation_criteria for each row
begin
if (select ifnull(sum(evaluation_weight),0) from evaluation_criteria) + new.evaluation_weight - old.evaluation_weight>= 100 then
signal SQLSTATE VALUE '99999' SET MESSAGE_TEXT = 'The limit of evaluation_weight has been reached. UPDATE fails. ';
end if;
end//
delimiter ;

How to write a stored procedure in MySQL that displays two messages when called

The goal here is to write a script attempts to insert a new category into categories table and if the insert was successful the message:
1 row was inserted
If the update is unsuccessful, the procedure should display this message:
Row was not inserted - duplicate entry
Whenever I run this script, I keep getting the second message no matter how many times I run it, when really it should display the first message, followed by the second. Here is my script. Can someone please help me spot what I'm overlooking? Thank you.
use my_guitar_shop;
/*drop procedure if exists add_category;*/
DELIMITER //
CREATE PROCEDURE add_category(
in categories VARCHAR(100)
)
begin
declare duplicate_entry_for_key TinyINT DEFAULT FALSE;
declare continue handler for 1062
SET duplicate_entry_for_key = TRUE;
insert into categories values (5, 'Electric');
select '1 row was inserted.' as message;
if duplicate_entry_for_key = true then
select 'Row was not inserted - duplicate entry.' as message;
end if;
end //
DELIMITER ;
/* call the stored procedure with 'Gibson' */
call add_category('Gibson');
call add_category('Gibson');
You should set duplicate_entry_for_key to True. If data insert is successful.
Do something like below after insert operation.
SET duplicate_entry_for_key = last_insert_id();
OR see the below example for bit check.
For example:
START TRANSACTION; -- Begin a transaction
INSERT INTO categories
VALUES
(
5
,'Electric'
);
IF ROW_COUNT() > 0 THEN -- ROW_COUNT() returns the number of rows updated/inserted/deleted
SET duplicate_entry_for_key = TRUE;
COMMIT; -- Finalize the transaction
ELSE
SET duplicate_entry_for_key = False;
--You can ROLLBACK the transaction also - Revert all changes made before the transaction began
END IF

INSERT INTO if conditions are met

A user is only meant to have up to 3 keys registered to his account at any one time. To add a new key, the user must first delete another key to "make room" for a new one.
I want this to be checked server-side, but I can't get the query to work. Here is what I tried:
IF (SELECT COUNT(serial_key_nbr)
FROM keys_table WHERE user_id = 9) <= 2
THEN INSERT INTO keys_table (user_id, serial_key_nbr)
VALUES (9, 'abc123')
How to do this?
You can use the below mention Script for the same:
INSERT INTO keys_table (user_id, serial_key_nbr)
SELECT 9, 'abc123' FROM DUAL
WHERE
(SELECT COUNT(serial_key_nbr)
FROM keys_table WHERE user_id = 9)<=2
if you want to use an if to do a conditional select then I would put it in a variable like so.
BEGIN
DECLARE var1 INT;
SELECT COUNT(serial_key_nbr) INTO var1
FROM keys_table
WHERE user_id = 9;
IF var1 <= 2
THEN
INSERT INTO keys_table (user_id, serial_key_nbr)
VALUES (9, 'abc123')
END IF;
A trigger might be the way to go. If a condition is met, a trigger before inserting in the table can perform an invalid operation and cause the insert operation to fail:
delimiter $$
create trigger keep_three before insert on keys_table for each row
begin
if (select count(serial_key_nbr) from keys_table where user_id = new.user_id) >= 3 then
insert into non_existent_table (non_existent_field) values (new.user_id);
end if;
end$$
delimiter ;
Ugly, but it might work.
Reference:
"MySQL Triggers: How do you abort an INSERT, UPDATE or DELETE with a trigger?"
Another solution (better I think) is to forcibly delete an entry before attepting the insert. When there are less than 3 entries, the insert procedes normally:
delimiter $$
create trigger keep_three before insert on keys_table for each row
begin
while (select count(serial_key_nbr) from keys_table where user_id = new.user_id) >= 3 do
delete from keys_table where user_id = new.user_id
-- OPTIONAL: Add an ordering criteria to define which entry is deleted first
limit 1;
end while;
end$$
delimiter ;
I think this is cleaner.
A third way (I've found it here). It will return an error message (by signaling sqlstate 45000: Unhandled user defined exception) associated with the defined condition:
delimiter $$
create trigger keep_three before insert on keys table for each row
begin
declare msg varchar(255);
declare n int default 0;
set n = (select count(serial_key_nbr) from keys_table where user_id = new.user_id);
if n >= 3 then
set msg = "INSERT failed: There must be only three entries for each user. Delete an entry first";
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = msg;
end if;
end$$
delimiter ;
A cleaner version of my first option.

how can multiple values be inserted in a table skipping few values in mysql

I can enforce data restriction at the time of data insertion in a table using a trigger like following:
create table com(id int);
DELIMITER ;;
CREATE TRIGGER checkage_bi BEFORE INSERT ON com FOR EACH ROW
BEGIN
DECLARE dummy,baddata INT;
SET baddata = 0;
IF NEW.id > 20 THEN
SET baddata = 1;
END IF;
IF NEW.id < 1 THEN
SET baddata = 1;
END IF;
IF baddata = 1 THEN
SELECT CONCAT('Cannot Insert This Because id ',NEW.id,' is Invalid')
INTO dummy FROM information_schema.tables;
END IF;
END;;
this will restrict the values which will not meet the restriction condition.
But the problem is that if I insert multiple values along then for some values which do not meet the condition the other values will also be restricted from entry to table.
What I want is that when I insert multiple values along then the values that do not meet the condition should be skipped and the rest get inserted into the table
i.e. no any error is given.
Only the the bad values will be skipped and the other values will be inserted that's it.
Please give me some idea to do so.Thanks in advance...
You should better use stored Procedures rather than triggers for this purpose because you are not permitted within a stored function or trigger to modify a table that is already being used (for reading or writing) by the statement that invoked the function or trigger itself.
DELIMITER ;;
create table com(id int,var char(40));;
create procedure Validate(IN id int,IN var char(40))
BEGIN
declare entry_id int;
SET entry_id=id;
IF (id > 20) OR (id < 1) THEN
SET entry_id=NULL;
END IF;
insert into com values(entry_id,var);
END;;
Here is the output screen

Execute query based on number of rows?

I'm not too great with MySQL, but I'm trying to create a trigger so that whenever a row is inserted, if the total count of rows in the table is bigger than 10 a certain row is deleted.
What I'm looking for, without the trigger syntax, is something like this:
IF (SELECT COUNT(*) FROM table) > 10 THEN
//do some stuff
END IF;
However that does not seem to be acceptable syntax. How should I go about doing this?
DELIMITER &&
CREATE TRIGGER trigger_name AFTER INSERT ON table_name FOR EACH ROW
BEGIN
DECLARE x INT;
SET x = (SELECT count(*) FROM table_name);
IF x > 10 THEN
DELETE FROM table_name where condition;
END IF;
END&&
DELIMITER ;
select count(1) into #cnt from table;
if (#cnt > 10) then
// do some stuff
end if;
instead of #cnt you can used declared variable