I wanted to write a trigger which deletes the oldest DB entry if a new one is inserted and the rowcount is larger than 3600 rows. Unfortunately, there is a error(1064) in line 7, but I don't know how to fix it. The column time if defined by using DATETIME in mysql.
CREATE TRIGGER maxRows BEFORE INSERT ON table1
FOR EACH ROW
BEGIN
IF ((SELECT COUNT(*) FROM table1) = 3600) THEN
DELETE FROM table1
ORDER BY time ASC
LIMIT 1;
END IF;
END;
As you have some DML sentences inside your trigger, try changing the delimiters
DELIMITER $$
CREATE TRIGGER maxRows BEFORE INSERT ON table1
FOR EACH ROW
BEGIN
IF ((SELECT COUNT(*) FROM table1) = 3600) THEN
DELETE FROM table1
ORDER BY time ASC
LIMIT 1;
END IF;
END;
END $$
DELIMITER ;
Related
I have two stored procedures in MySql. One of them does the calculation and returns everything in groups. With another stored procedure, I have a WHILE statement that runs for each month and calls the first stored procedure. I want to get the result of each group and save them in a table.
The code is something like:
CREATE PROCEDURE `first`(IN `start` date, **it should be list of items** )
begin
SET result = 0;
SELECT
item.name,
sum(amount) *INTO result*
FROM
FOO
INNER JOIN
BAR ON id = id
WHERE
date(someDate) < date(start)
group by something;
end
And the runner is something like:
CREATE PROCEDURE `runner`(IN `from` date, IN `to` date)
BEGIN
set dateTo = date(to);
set dateFrom = date(from);
WHILE DATE(dateFrom) <= DATE(dateTo) DO
call first(dateFrom, #res);
// here I need another loop through all results of the first procedure to insert each one of them in the following line.
insert into table_x (**some values which have been returned**);
SET dateFrom = DATE_ADD(dateFrom, INTERVAL 1 month);
END WHILE;
END
I don-' think that the loop and the second procedure ist really necessary
MySQL can't return table arrays or something of that kind, but you can use temporary tables
DELIMITER $$
CREATE PROCEDURE `first`(IN `start` date )
begin
DROP TEMPORARY TABLE IF EXISTS myTable;
CREATE TEMPORARY TABLE myTABLE
SELECT
item.name,
sum(amount)
FROM
FOO
INNER JOIN
BAR ON id = id
WHERE
date(someDate) < date(start)
group by something;
end$$
DELIMITER ;
Outer procdudre
DELIMITER $$
CREATE PROCEDURE `runner`(IN `_from` date, IN `_to` date)
BEGIN
set dateTo = date(_to);
set dateFrom = date(_from);
WHILE DATE(dateFrom) <= DATE(dateTo) DO
call first(dateFrom, #res);
insert into table_x (SELECT * FROM myTable);
SET dateFrom = DATE_ADD(dateFrom, INTERVAL 1 month);
END WHILE;
END$$
DELIMITER ;
You ca make dynamic sql work with different variables
DELIMITER $$
CREATE PROCEDURE `first`(IN `_start` date , IN _group varchar(100))
begin
DROP TEMPORARY TABLE IF EXISTS myTable;
SET #sql := CONCAT("
CREATE TEMPORARY TABLE myTABLE
SELECT
item.name,
sum(amount)
FROM
FOO
INNER JOIN
BAR ON id = id
WHERE
date(someDate) < date(",_gRoup,")
group by",_goup,";");
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
end$$
DELIMITER ;
This might work, if all ** some values ** are replaced.
Minimal version of MySQL needed is 8.0 (or an equivalent MariaDB version).
The two variables #from and #to are set to let this script know from which data to which date is needed.
This code is untested, because OP wrote "I have two stored procedures in MySql", but he uses things like "** some values **", which make the two stored procedures invalid (sigh).
Final remark: It is, of course, possible to wrap this complete statement into a stored procedure. (If above corrections are made)
set #from = '2021-05-01';
SET #to = '2021-06-13';
insert into table_x (** some values **)
WITH recursive dates AS (
SELECT #from as d
UNION ALL
SELECT date_add(d, INTERVAL 1 DAY)
FROM dates
WHERE d<#to
)
SELECT d, **some values which have been returned**
FROM dates
CROSS JOIN (
SELECT
item.name,
sum(amount)
FROM
FOO
INNER JOIN
BAR ON id = id
WHERE
date(someDate) < date(d)
group by something) sq
I'm trying to do a room capacity validation for a specific date using a before trigger.
This is the current trigger I'm using:
delimiter $$
create trigger my_insert_trigger before insert on my_table
for each row
begin
if (select count(*) from my_table where room_type = new.room_type) > 3 then
signal sqlstate '45000';
end if;
end;
$$
delimiter ;
I currently have two columns in the same table which are date and room, this is my desired output
However this would not be the case because the trigger will still limit 'Single' three times regardless of date.
do a room capacity validation for a specific date
Just add the date to the control query:
delimiter $$
create trigger my_insert_trigger before insert on my_table
for each row
begin
if (
select count(*)
from my_table t
where t.room_type = new.room_type and t.date = new.date
) >= 3 then
signal sqlstate '45000';
end if;
end;
$$
delimiter ;
Note: because it has condition > 3, your existing code would allow 4 records per room. I changed that to >= 3 so only 3 records are allowed per room and date, which seems to be what you are looking for.
This is my trigger.
I want to make trigger on 1 table (rezervare).
Trigger
DELIMITER //
CREATE TRIGGER verificare_nr_locuri
BEFORE INSERT ON Rezervare
FOR EACH ROW
BEGIN
IF ( SELECT Masa.NrLocuri FROM Rezervare, Masa
WHERE Masa.NumarMasa = Rezervare.NumarMasa ) < Rezervare.NumarPersoane THEN
SET NEW.NumarMasa = NULL;
END IF;
END //
DELIMITER ;
INSERT INTO Rezervare VALUES (123,106,2,'2016-12-11','2016-12-24',5);
INSERT INTO Rezervare VALUES (124,106,2,'2016-12-11','2016-12-24',4);
When I execute the trigger, it has been created. But, when I insert data into table rezervare, It become
#1109 - Unknown table 'rezervare' in field list.
How can I resolve this?
Table
I think you might need to use a JOIN for your SELECT clause.
BEGIN
IF (SELECT Masa.NrLocuri, Rezervare.NumarMasa FROM Masa JOIN Rezervare
WHERE Masa.NumarMasa = Rezervare.NumarMasa) < Rezervare.NumarPersoane THEN
SET NEW.NumarMasa = NULL;
END IF;
my problem is as follows:
Table A contains list of "Tasks"
Table B contains "TaskProgress" - just an information about time spent on task, user ID, task ID and note
On table A (Tasks), I have trigger, which updates datetime of last change - column DateChanged (intended to capture datetime of edits made by user)
On table B (TaskProgress) I have trigger, which updates total time spent on a task (sum all times for given Task_ID and update column TotalTime in table A)
I wish to update DateChanged in Table A only when user mades the update (which is every time except when trigger on table B updates TotalTime)
So I wonder, whether there is a way how to tell the database not to fire TRIGGER when updating the values in another trigger.
/* set date of last change and date od closing of task */
DELIMITER $$
CREATE TRIGGER before_tasks_update
BEFORE UPDATE ON tasks
FOR EACH ROW BEGIN
SET new.DateChanged = NOW();
IF new.Status_ID = 3 THEN
SET new.DateClosed = NOW();
END IF;
END$$
DELIMITER ;
/* set total time spent on task */
DELIMITER $$
CREATE TRIGGER after_taskprogress_insert
AFTER INSERT ON taskprogress
FOR EACH ROW BEGIN
DECLARE sumtime TIME;
SET #sumtime := (SELECT SEC_TO_TIME( SUM( TIME_TO_SEC( `timeSpent` ) ) )
FROM taskprogress WHERE Task_ID = new.Task_ID);
UPDATE `tasks` SET TimeReal = #sumtime WHERE ID = new.Task_ID;
END $$
DELIMITER ;
I use MySQL 5.5.40
Thanks, zbynek
Add a check to verify that the update implies a new TimeReal value,since only the second trigger updates that column.
DELIMITER $$
CREATE TRIGGER before_tasks_update
BEFORE UPDATE ON tasks
FOR EACH ROW BEGIN
IF new.TimeReal=old.TimeReal THEN SET new.DateChanged = NOW();
END IF;
IF new.TimeReal=old.TimeReal AND new.Status_ID = 3 THEN
SET new.DateClosed = NOW();
END IF;
END$$
DELIMITER ;
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