I have two tables, round and event. One round has many events.
create table round (
round_id INTEGER AUTO_INCREMENT NOT NULL,
round_start_date DATETIME NOT NULL,
round_end_date DATETIME NOT NULL,
CONSTRAINT round_pk PRIMARY KEY (round_id)
);
create table event (
event_id INTEGER AUTO_INCREMENT NOT NULL,
round_id INTEGER NOT NULL,
event_date DATETIME NOT NULL,
CONSTRAINT event_pk PRIMARY KEY (event_id),
CONSTRAINT round_fk FOREIGN KEY (round_id) REFERENCES round (round_id),
);
When a row is inserted into the event table, I want to use a trigger to compare the event_date field of the newly inserted row to the round_start_date and round_end_date fields in its corresponding entry in the round table. If event_date is earlier than round_start_date, round_start_date should be updated with the new event_date. If event_date is after round_end_date, round_end_date should be updated with the new event_date.
This is my trigger. It does not work, and I do not understand why. I cannot find anywhere on the web where anyone else has tried to use a datetime type in a trigger, so I have no frame of reference for where I am going wrong.
create trigger update_round_date
after insert on event for each row
begin
declare curSdate datetime;
declare curEdate datetime;
set curSdate = (select round_start_date from round where round_id = NEW.round_id);
set curEdate = (select round_end_date from round where round_id = NEW.round_id);
if (NEW.event_date < curSdate) then
update round set round_start_date = NEW.event_date where round_id = NEW.round_id;
else if (NEW.event_date > curEdate) then
update round set round_end_date = NEW.event_date where round_id = NEW.round_id;
end if;
end;
EDIT: I simply can't create the trigger. phpMyAdmin gives me this error:
"#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 '' at line 4"
EDIT 2: Updated with a delimiter set
DELIMITER $$
create trigger update_round_date
after insert on event for each row
begin
declare curSdate datetime;
declare curEdate datetime;
set curSdate = (select round_start_date from round where round_id = NEW.round_id);
set curEdate = (select round_end_date from round where round_id = NEW.round_id);
if (NEW.event_date < curSdate) then
update round set round_start_date = NEW.event_date where round_id = NEW.round_id;
else if (NEW.event_date > curEdate) then
update round set round_end_date = NEW.event_date where round_id = NEW.round_id;
end if;
end$$
This returns the error: "#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 '' at line 13"
MySQL is probably stopping at the first ';', interpreting your command as:
create trigger update_round_date
after insert on event for each row
begin
declare curSdate datetime;
You have to set your delimiter to something else first, then terminate the create trigger command with that delimiter instead (and put the delimiter back at the end):
delimiter ^
create trigger update_round_date
after insert on event for each row
begin
...
end;
^
delimiter ;
I believe the last semicolon after end may be necessary.
There may be a problem with delimiters in phpmyadmin, try to use this trigger -
CREATE TRIGGER trigger1
AFTER INSERT
ON event
FOR EACH ROW
UPDATE
round
SET
round_start_date =
IF(NEW.event_date < round_start_date, NEW.event_date, round_start_date),
round_end_date =
IF(NEW.event_date > round_end_date, NEW.event_date, round_end_date)
WHERE
round_id = NEW.round_id;
Related
Hello I'm trying to create a trigger(or more) in order to calculate the time difference in a mysql table (I'm using mysql 5.7.21).
The table I have is this :
CREATE TABLE people(
username VARCHAR(255) NOT NULL,
state VARCHAR(255) NOT NULL DEFAULT 'not active',
PRIMARY KEY(username)
);
Some explanation about the table : The username column is self-explanatory and the state column get only 1 out of 3 values : 'active', 'not active','working' .
Specifically a person can change from 'active' to 'not active'/'working' and vice-versa but cannot change from 'not active' to 'working' or from 'working' to 'not active'.
What I want to do is to keep track of how much time has a person been active/working for.
Now my idea is have a table like this :
Create table Time(
username VARCHAR(255) NOT NULL,
timestarted TIME,
timeended TIME,
timeworking TIME,
FOREIGN KEY (username) REFERENCES people(username)
);
My first guess was to use the CURRENT_TIME() function to keep track of state using triggers.
What I did is :
Delimiter $$
CREATE TRIGGER time_calculation
BEFORE Update
ON people
FOR EACH ROW BEGIN
DECLARE #times time;
DECLARE #timee time;
DECLARE #timet time;
IF OLD.state = 'not active' THEN
UPDATE Time SET timestart = CURRENT_TIME() WHERE username = new.username;
END IF;
IF NEW.state = 'not active' THEN
set #times = (select timestarted from time where username = new.username);
set #timee = (select timeended from time where username = new.username);
set #timet = (select timeworking from time where username = new.username);
UPDATE Time SET timeend = CURRENT_TIME(),timeworking = (TIMEDIFF(times,timee)+timet) WHERE username = new.username;
END IF;
END$$
According to this trigger. Every time someone switches from 'not active' to 'active' the Time table will get the current time of that switch as timestart.When someone switches to 'not active' the Time table will get the current time as timeend and it will add the difference between timestart and timeend to timeworking. The trigger shows the following error :
ERROR 1064 (42000): 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 'DECLARE #times time;
DECLARE #timee time;
DECLARE #timet time;
BEGIN
IF OLD.state =' at line 5
Don't know what's wrong with it. Any ideas?
Well I found a way to solve this problem although it wasn't as I expected it. I made some changes in the table structure as follows :
Create table people (
username VARCHAR(255) NOT NULL,
Primary Key (username)
);
Create table characteristics (
username VARCHAR(255) NOT NULL,
state VARCHAR(25) NOT NULL DEFAULT 'not active',
timestart TIME,
timestop TIME,
timetotal TIME NOT NULL DEFAULT '00:00:00',
FOREIGN KEY(username) REFERENCES people(username)
);
As for the trigger to get the time difference it's as follows :
Delimiter $$
CREATE TRIGGER time_calculation
BEFORE Update
ON characteristics
FOR EACH ROW BEGIN
IF OLD.state = 'not active' && NEW.state != 'not active' THEN
SET NEW.timestart = CURRENT_TIME();
END IF;
IF NEW.state = 'not active' && OLD.state != 'not active' THEN
SET NEW.timestop = CURRENT_TIME();
SET NEW.timetotal = ADDTIME(OLD.timetotal,TIMEDIFF(NEW.timestop, OLD.timestart));
END IF;
END$$
Delimiter ;
Hope this helps anyone having the same problem with me !
TRIGGER `dn_name`.`schedule_arrive` AFTER INSERT
ON `dn_name`.`administration_schedule`
FOR EACH ROW BEGIN
DECLARE approx_hr INT(11), update_hr DATETIME;
SELECT approx_hr FROM `administration_routes` WHERE id = NEW.route_id INTO approx_hr;
SELECT DATE_ADD(new.depart_time, INTERVAL approx_hr HOUR_MINUTE) INTO update_hr;
UPDATE administration_schedule SET arrive_time=approx_hr WHERE id = NEW.id;
END$$
On running insert query, I designed to select approx hour from route table with related id and set that value to approx_hr, increase datetime from new inserted depart time and assign to update_hr and finally update the arrive_time field in trigger enabled same table. But on executing my query, the system show as follows;
Error Code: 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 ', update_hr datetime;
select approx_hr from administration_routes where id =' at line 7
About the NEW.myColumn and OLD.myColumn, you can only use them when using "BEFORE" something. After an insert, you don't have an OLD.myColumn or NEW.myColumn gut a current one. for what you want to do, use "BEFORE INSERT" and change your "SELECT,... SELECT..., UPDATE..." to a simple
SET NEW.arrive_time = DATE_ADD(NEW.depart_time,INTERVAL ...);
Use a before update trigger:
CREATE TRIGGER `dn_name`.`schedule_arrive` BEFORE INSERT
ON `dn_name`.`administration_schedule`
FOR EACH ROW
BEGIN
DECLARE approx_hr INT(11), update_hr DATETIME;
SELECT approx_hr FROM `administration_routes` WHERE id = NEW.route_id INTO approx_hr;
SELECT DATE_ADD(new.depart_time, INTERVAL approx_hr HOUR_MINUTE) INTO update_hr;
SET NEW.arrive_time = approx_hr;
END$$
Please I did this trigger to update table rating after each insert when 2 columns (id_prof,id_etud) inserted are already in the table but it gives mi this error
> #1064 - You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 6
The trigger :
CREATE TRIGGER Before_Insert_Rate
BEFORE INSERT ON rating
FOR EACH ROW
BEGIN
IF (EXISTS(SELECT * FROM rating WHERE id_prof=NEW.id_prof and id_etud = NEW.id_etud)) THEN
UPDATE `rating` SET `rate` = NEW.rate WHERE `id_prof` = NEW.id_prof and `id_etud` = NEW.id_etud;
ELSE INSERT INTO rating VALUES (NEW.idprof,New.rate,New.id_etud);
END IF
END
DELIMITER ;
You must set the DELIMITER before. Change it to:
DELIMITER //
CREATE TRIGGER Before_Insert_Rate
BEFORE INSERT ON rating
FOR EACH ROW
BEGIN
IF (EXISTS(SELECT * FROM rating WHERE id_prof=NEW.id_prof and id_etud = NEW.id_etud)) THEN
UPDATE `rating` SET `rate` = NEW.rate WHERE `id_prof` = NEW.id_prof and `id_etud` = NEW.id_etud;
ELSE INSERT INTO rating VALUES (NEW.idprof,New.rate,New.id_etud);
END IF
END; //
DELIMITER ;
from the official reference manual.
A trigger can access both old and new data in its own table. A trigger
can also affect other tables, but it is not permitted to modify a
table that is already being used (for reading or writing) by the
statement that invoked the function or trigger.
This means no query on table X can INSERT, UPDATE, or DELETE from table X; it also means that if a trigger on table X modifies table Y, it will fail for any query using both table X and Y that "triggers" it.
Example: UPDATE x INNER JOIN y ON x.id = y.id SET x.something = 1, y.something = 2 will cause a BEFORE UPDATE ON x trigger (that updates, inserts, or deletes from y) to fail.
I solved it using ON DUPLICATE KEY on a query instead of trigger
CREATE TABLE `rating` (
`id_prof` int(11) NOT NULL,
`rate` float NOT NULL,
`id_etud` int(11) NOT NULL,
UNIQUE (id_prof,id_etud)
)
the query :
INSERT INTO rating (id_prof,rate,id_etud) VALUES (1,2,5)
ON DUPLICATE KEY UPDATE rate=2
What may be the possibilities of getting an error in the following query?
DELIMITER $$
CREATE PROCEDURE `tbl_assessment_notes`(
`var_reason` VARCHAR,
'var_attr2' VARCHAR,
'var_note' VARCHAR
)
BEGIN
IF EXISTS
(
SELECT
*
FROM
tbl_assessment_notes
WHERE
reason = var_reason AND attr2 = var_attr2
) THEN
UPDATE
tbl_assessment_notes
SET
note = CONCAT(note, var_note),
TIMESTAMP = 'CURRENT_TIMESTAMP'
WHERE
attr1 = var_attr1 AND reason = var_reason ELSE
INSERT
INTO
tbl_assessment_notes(
pk_assess_note_id,
attr2,
attr3,
reason,
note,
TIMESTAMP
)
VALUES(
NULL,
var_attr2,
NULL,
'confirmation',
var_note,
'CURRENT_TIMESTAMP'
) ;
END IF ;
END $$
DELIMITER ;
I'm getting the following error:
#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 '
'var_reason' VARCHAR,
'var_attr2' VARCHAR,
`var_note` VARCHAR,
'var' at line 2
Basically what I'm trying to do is to update a row if it exists or else creates a new row and insert values into it.
Please use updated query
DELIMITER $$
CREATE PROCEDURE `tbl_assessment_notes`
(var_reason VARCHAR(255),
var_attr2 VARCHAR(255),
var_note VARCHAR(255))
BEGIN
IF EXISTS
(
SELECT
*
FROM
tbl_assessment_notes
WHERE
reason = var_reason AND attr2 = var_attr2 ) THEN UPDATE tbl_assessment_notes SET note = CONCAT(note, var_note), TIMESTAMP
= 'CURRENT_TIMESTAMP' WHERE attr1 = var_attr1 AND reason = var_reason ELSE INSERT INTO tbl_assessment_notes(
pk_assess_note_id,
attr2,
attr3,
reason,
note,
TIMESTAMP) VALUES(NULL,var_attr2,NULL,'confirmation', var_note, 'CURRENT_TIMESTAMP' ) ;
END IF ;
END $$
DELIMITER ;
I need to check before insert into 'year' column of ( Academic Report) that it's not less than the year of 'enrollment date' column in (student)
my tables :
CREATE TABLE STUDENT
(
BCN INT (10) ,
Enrollment_Date timestamp not null default CURRENT_TIMESTAMP,
primary key (BCN),
);
CREATE TABLE ACADEMIC_REPORT
(
Stud_Num INT(10) ,
Year year ,
primary key (Stud_Num , Year ),
foreign key (Stud_Num ) references STUDENT( BCN )
ON DELETE restrict ON UPDATE CASCADE
);
I've try this :
/* ACADEMIC_REPORT._Year Constraint "BEFORE INSERT" */
delimiter //
CREATE TRIGGER ReportYearBIN BEFORE INSERT ON ACADEMIC_REPORT
FOR EACH ROW
BEGIN
declare num int(10);
SET num= (SELECT BCN
FROM STUDENT , ACADEMIC_REPORT
WHERE BCN = ACADEMIC_REPORT.Stud_Num );
IF (ACADEMIC_REPORT.Year < YEAR(num.Enrollment_Date))
THEN
SIGNAL SQLSTATE '10000'
SET MESSAGE_TEXT = 'Error....!';
END IF;
END;
// delimiter ;
but it causes this error during insert
Error Code: 1054. Unknown column 'ACADEMIC_REPORT.Year' in 'field list'
How can I do that constraint ?
Using MySql workbench 6.3
Thank you in advance.
Okay, I created a select statement for the conditions that you want to generate the error on. If the student exists for this report and the report year is less than the students enrollment date it will generate one or more rows for the select query. The proceeding FOUND_ROWS() will then be greater than 0 which will trigger your error message.
CREATE TRIGGER ReportYearBIN BEFORE INSERT ON ACADEMIC_REPORT
FOR EACH ROW
BEGIN
SELECT * FROM STUDENT WHERE BCN=new.Stud_Num AND new._year < Enrollment_Date
IF (SELECT FOUND_ROWS() > 0)
THEN
SIGNAL SQLSTATE '10000'
SET MESSAGE_TEXT = 'Error....!';
END IF;
END;
I've figured out the problem :)
This statement is completely wrong,
YEAR(num.Enrollment_Date)
because it's not correct to write attribute.attribute, you can only use Table.Attribute.
So, here is the solution
/* ACADEMIC_REPORT._Year Constraint "BEFORE INSERT" */
delimiter //
CREATE TRIGGER ReportYearBIN BEFORE INSERT ON ACADEMIC_REPORT
FOR EACH ROW
BEGIN
declare Enroll timestamp;
SET Enroll = (SELECT Enrollment_Date
FROM STUDENT
WHERE BCN = new.Stud_Num);
IF ( new._year < YEAR(Enroll))
THEN
SIGNAL SQLSTATE '10000'
SET MESSAGE_TEXT = 'Error..The Report year cannot be less than the enrollment year..!';
END IF;
END;
// delimiter ;