So what I'm trying to do is build a web application for sports applications (specifically soccer). Right now, I'm having trouble with a trigger that is supposed to update the standings after a match score is recorded. In this example, I have a 'game' table, and a 'standings' table, like so.
mysql> describe game;
+-----------------+------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+------------+------+-----+---------+-------+
| sid | int(11) | NO | PRI | NULL | |
| fid | int(11) | NO | PRI | NULL | |
| lid | int(11) | NO | PRI | NULL | |
| htid | int(11) | NO | PRI | NULL | |
| atid | int(11) | NO | PRI | NULL | |
| date | date | NO | | NULL | |
| time | time | NO | | NULL | |
| h_g | int(11) | NO | | 0 | |
| a_g | int(11) | NO | | 0 | |
| has_been_played | tinyint(1) | NO | | 0 | |
+-----------------+------------+------+-----+---------+-------+
10 rows in set (0.00 sec)
mysql> describe standings;
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| tid | int(11) | NO | PRI | NULL | |
| sid | int(11) | NO | PRI | NULL | |
| lid | int(11) | NO | PRI | NULL | |
| pld | int(11) | NO | | 0 | |
| pts | int(11) | NO | | 0 | |
| h_w | int(11) | NO | | 0 | |
| h_t | int(11) | NO | | 0 | |
| h_l | int(11) | NO | | 0 | |
| h_gf | int(11) | NO | | 0 | |
| h_ga | int(11) | NO | | 0 | |
| a_w | int(11) | NO | | 0 | |
| a_t | int(11) | NO | | 0 | |
| a_l | int(11) | NO | | 0 | |
| a_gf | int(11) | NO | | 0 | |
| a_ga | int(11) | NO | | 0 | |
+-------+---------+------+-----+---------+-------+
15 rows in set (0.00 sec)
Where h/atid (and tid), fid, sid, and lid are foreign keys to team, field, season, and league tables, respectively.
I want to create a trigger after a game is updated. The current design I am aiming for in this application is that when a "game" is inserted, it has not been "played" yet and when it is updated, then the score is recorded and then the game is then considered "played." So here's a section of the trigger:
CREATE TRIGGER `update_standing` AFTER UPDATE ON `game`
FOR EACH ROW
BEGIN
# If a score has been recorded already, we'll reverse the old score
# before updating the new score.
IF OLD.has_been_played THEN
# The Home Team previously recorded a win
IF OLD.h_g > OLD.a_g THEN
# Home win
UPDATE standings
SET pld = pld - 1,
h_w = h_w - 1,
pts = pts - 3,
h_gf = h_gf - OLD.h_g,
h_ga = h_ga - OLD.a_g
WHERE tid = OLD.htid
AND sid = OLD.sid
AND lid = OLD.lid;
# Away loss
UPDATE standings
SET pld = pld - 1,
a_l = a_l - 1,
a_gf = a_gf - OLD.a_g,
a_ga = a_ga - OLD.h_g
WHERE tid = OLD.atid
AND sid = OLD.sid
AND lid = OLD.lid;
ENDIF;
ENDIF;
END;
And for some reason, I'm getting these errors, and I'm not sure why.
mysql> source new_trigger_myfam.sql
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 '' at line 18
ERROR 1054 (42S22): Unknown column 'OLD.atid' in 'where clause'
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 'ENDIF' at line 1
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 'ENDIF' at line 1
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 'END' at line 1
Is there something visibly wrong with my syntax? I understand that I could do the two update queries in one using case/when/then. Essentially, in this snippet of the trigger, I am reversing a previous update, and then there's more code actually making the rest of the update happen. I'm pretty new to triggers, so help is always appreciated.
As per the documentation, the IF block terminator in MySQL is two words: END IF.
So I got it with the help of someone else.
I need to wrap a delimiter around the triggers because the first instance of ; means that the entire trigger is "ended", when obviously that is not what I want.
Really stupid if you ask me, but what can you do?
Related
I have a table called 'exam_paper_details', described below:
create table exam_paper_details(exam_id varchar(5) primary key,exam_date date,exam_subject varchar(10),exam_paper_creation_prof varchar(60),exam_paper_creation_prof_division varchar(20),exam_paper_creation_prof_role varchar(10),exam_paper_creation_prof_id varchar(7));
+-----------------------------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------------------------------+-------------+------+-----+---------+-------+
| exam_id | varchar(5) | NO | PRI | NULL | |
| exam_date | date | YES | | NULL | |
| exam_subject | varchar(10) | YES | | NULL | |
| exam_paper_creation_prof | varchar(60) | YES | | NULL | |
| exam_paper_creation_prof_division | varchar(20) | YES | | NULL | |
| exam_paper_creation_prof_role | varchar(10) | YES | | NULL | |
| exam_paper_creation_prof_id | varchar(7) | YES | | NULL | |
+-----------------------------------+-------------+------+-----+---------+-------+
7 rows in set (0.01 sec)
Now I want to insert rows using concat_ws keyword.
I have tried this quesry:
insert into exam_paper_details (exam_id,exam_date,exam_subject,concat_ws(',',exam_paper_creation_prof,exam_paper_creation_prof_division,exam_paper_creation_prof_role,exam_paper_creation_prof_id)) values ('001','2022-02-27','abc','Mr. XYZ,Science,Assi. Prof,A123');
Gives me 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 '(',',exam_paper_creation_prof,exam_paper_creation_prof_division,exam_paper_creat' at line 1
Again I have tried this below query:
insert into exam_paper_details select '001' as exam_id,'2022-02-27' as exam_date,'abc' as exam_subject,concat_ws(',',exam_paper_creation_prof,exam_paper_creation_prof_division,exam_paper_creation_prof_role,exam_paper_creation_prof_id)='Mr. XYZ,Science,Assi. Prof,A123' from exam_paper_details;
Gives me following error:
ERROR 1136 (21S01): Column count doesn't match value count at row 1
Again I have tried following one:
insert into exam_paper_details (exam_id,exam_date,exam_subject,exam_paper_creation_prof,exam_paper_creation_prof_division,exam_paper_creation_prof_role,exam_paper_creation_prof_id) select * from (select '001' as exam_id,'2022-02-27' as exam_date,'abc' as exam_subject,concat_ws(',',exam_paper_creation_prof,exam_paper_creation_prof_division,exam_paper_creation_prof_role,exam_paper_creation_prof_id)=('Mr. XYZ,Science,Assi. Prof,A123')) as tmp;
This gives me following error:
ERROR 1054 (42S22): Unknown column 'exam_paper_creation_prof' in 'field list'
Please help me.
I have looked at a lot of other questions asked on this topic and still can not figure out what the error of my code is in SQL. I created a table called easy_drinks and when I try to insert one record it is giving me an error. Can someone please explain to me the error? Also, what is the best way to debug this kind of error in the future if I can't find out the issue?
mysql> DESC easy_drinks;
+------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+-------+
| drink_name | varchar(40) | NO | | NULL | |
| main | varchar(20) | NO | | NULL | |
| amount1 | decimal(4,2) | NO | | NULL | |
| second | varchar(20) | NO | | NULL | |
| amount2 | decimal(4,2) | NO | | NULL | |
| directions | blob | NO | | NULL | |
+------------+--------------+------+-----+---------+-------+
6 rows in set (0.00 sec)
mysql> INSERT INTO easy_drinks (drink_name, main, amount1, second, amount2, directions) VALUES (‘Blackthorn’, ‘tonic water’, 1.5, ‘pineapple juice’, 1, ‘stir with ice, strain into cocktail glass with lemon twist’);
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 'water’, 1.5, ‘pineapple juice’, 1, ‘stir with ice, strain into c' at line 1
I am running MySQL version 5.6.22
Replace your quotes from ` to '
The following is my table schema:
+--------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+-------+
| LicenceID | int(11) | NO | PRI | NULL | |
| PassingRTO | varchar(4) | NO | | NULL | |
| DLNO | int(15) | YES | | NULL | |
| DateOfIssue | date | NO | | NULL | |
| DateOfExpiry | date | NO | | NULL | |
| COV | varchar(6) | NO | | NULL | |
| DateOfBirth | date | NO | | NULL | |
| BloodGroup | varchar(3) | YES | | NULL | |
| FullName | varchar(50) | NO | | NULL | |
| FathersName | varchar(50) | YES | | NULL | |
| Address | varchar(150) | NO | | NULL | |
| PinCode | int(6) | NO | | NULL | |
| IssuingAuth | int(7) | NO | | NULL | |
| IDIA | int(11) | YES | | NULL | |
| Valid | tinyint(4) | NO | | NULL | |
+--------------+--------------+------+-----+---------+-------+
What i want to do is When i insert a new row, i want my DLNO as PassingRTO+LicenceID and IDIA as PassingRTO+IssuingAuth.
I tried the same using -
create trigger insert_combined
after insert on LicencesDB
for each row
BEGIN
set new.IDIA = concat(new.PassingRTO, new.IssuingAuth);
set new.DLNO = concat(new.PassingRTO,new.LicenceID);
END;
but gives me an error as -
ERROR 1362 (HY000): Updating of NEW row is not allowed in after
trigger ERROR 1193 (HY000): Unknown system variable 'DLNO' 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 'END' at line 1
Now I have two questions can we do this using multiple lines in triggers? and can't we combine two columns at the time of creating the table itself? like col1 = col2 + col3?
Thanks in advance!
don;t forget to change the DELIMITER
DELIMITER $$
create trigger insert_combined
after insert on LicencesDB
for each row
BEGIN
set new.IDIA = concat(new.PassingRTO, new.IssuingAuth);
set new.DLNO = concat(new.PassingRTO,new.LicenceID);
END $$
DELIMITER ;
Please check this link on mysql triggers. When you want to make an update on the current row being entered you can't use the after clause.
check http://dev.mysql.com/doc/refman/5.1/en/create-trigger.html
When you want to use
SET NEW.col_name = value
in your trigger, please note that you CANNOT use this with the AFTER the action, and must use it BEFORE the action.
Therefore, this will work:
CREATE TRIGGER sdata_insert BEFORE INSERT ON `sometable`
FOR EACH ROW
BEGIN
SET NEW.guid = UUID();
END
;
And this will NOT work:
CREATE TRIGGER sdata_insert AFTER INSERT ON `sometable`
FOR EACH ROW
BEGIN
SET NEW.guid = UUID();
END
;
Also you can probably do it in the code itself before even entering into the database.
I've been struggling with converting the following SQL to CDBCriteria to be used with a CActiveDataProvider:
"SELECT PresetDeviceLink., Device. FROM PresetDeviceLink INNER JOIN Device ON Device.id = PresetDeviceLink.deviceId WHERE Device.roomId = 1"
Table structure is as follows:
mysql> describe PresetDeviceLink;
+----------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+---------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| presetId | int(11) | NO | | NULL | |
| deviceId | int(11) | NO | | NULL | |
| state | int(11) | NO | | 0 | |
| value | int(11) | NO | | 32 | |
+----------+---------+------+-----+---------+----------------+
mysql> describe Device;
+-------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| ref | int(11) | NO | | NULL | |
| roomId | int(11) | NO | | NULL | |
| typeId | int(11) | NO | | NULL | |
| paired | tinyint(1) | NO | | 0 | |
| name | varchar(255) | YES | | NULL | |
| description | text | YES | | NULL | |
| dimmerPos | int(11) | NO | | 0 | |
+-------------+--------------+------+-----+---------+----------------+
My code in my controller is as follows:
$criteria = new CDbCriteria;
$criteria->select = 'PresetDeviceLink.*, Device.*';
$criteria->join = 'INNER JOIN Device ON Device.id = PresetDeviceLink.deviceId';
$criteria->condition = 'Device.roomId = 1';
$presetDeviceLink=new CActiveDataProvider('PresetDeviceLink', array(
'criteria' => $criteria,
));
When run I get the following error:
CDbCommand failed to execute the SQL statement: SQLSTATE[42S22]: <b>Column not
found</b>: 1054 Unknown column 'PresetDeviceLink.deviceId' in 'on clause'. The SQL
statement executed was: SELECT COUNT(*) FROM `PresetDeviceLink` `t` INNER JOIN
Device ON Device.id = PresetDeviceLink.deviceId WHERE Device.roomId = 1
The strange thing is, If I use 'Device' as the CActiveDataProvider source and change the join statement to join to 'PresetDeviceLink', it then complains that the Device.roomId column could not be found.
Do I just not understand how CActiveDataProvider works? It looks to me that I can only use a condition (in a join or where clause) from a field in the table that I pass to the CActiveDataProvider. Any advice?
PS - the SQL query works beautifully in the MySQL console.
Thanks in advance,
Ben
As is visible in the "The SQL statement executed was:" line, the first table was aliased to t. This is Yii's standard behaviour.
As a result of this, you should use that alias to refer to that table instead of PresetDeviceLink. Or you could try setting $criteria->alias = 'PresetDeviceLink'; before using it in the CActiveDataProvider, though I have not personally tried that option, it should work.
mysql> desc test;
+-------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| a | int(10) unsigned | NO | | NULL | |
| b | int(10) unsigned | NO | | NULL | |
| c | int(10) unsigned | NO | | NULL | |
| str | varchar(9) | YES | | NULL | |
+-------+------------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
mysql> CREATE TRIGGER Capitalize BEFORE INSERT ON test
-> SET NEW.str = UPPER(NEW.str)
-> ;
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 'SET NEW.str = UPPER(NEW.str)' at line 2
mysql>
I'm following this answer:
How to define a column that can automate capitalizing?
CREATE TRIGGER Capitalize BEFORE INSERT ON test
FOR EACH ROW
SET NEW.str = UPPER(NEW.str);
Heed the advice in the error message: "check the manual that corresponds to your MySQL server version for the right syntax to use."