whats wrong with my syntax?
CREATE
TRIGGER db_dhruniversity.trigger1
AFTER INSERT
ON jos_dhruprofile
FOR EACH ROW
BEGIN
UPDATE jos_users
SET jos_users.department = jos_dhruprofile.department
WHERE jos_users.id = jos_dhruprofile.uid
END
The syntax should be as follows:
DELIMITER $$ /* if you're not using an editor, you must change the delimiter*/
CREATE
TRIGGER ai_jos_dhruprofile_each
AFTER INSERT
ON jos_dhruprofile
FOR EACH ROW
BEGIN
UPDATE jos_users
SET jos_users.department = NEW.department
WHERE jos_users.id = NEW.uid; /*<<<--- ; after every stament */
END $$ /* changed delimiter after the end */
DELIMITER ; /*make sure you set the delimiter back to the default*/
Note on the naming scheme for triggers
I'd recommend naming your trigger ai (meaning after insert) so you know when it fires on which table, rather than a meaningless name like: db_dhruniversity.trigger1.
I always use [a/b]+[d/i/u]_tablename_each as the triggername, that way I always know when the triggers fires (before/after) for which event (insert/delete/update) and on which table.
It's also good practise to document that the trigger fires on each row, hence the each on the end of the trigger name.
Note that MySQL does not support triggers that fire once per statement yet (But that might change in future).
There are no delimiters in it:
DELIMITER ||
CREATE
TRIGGER db_dhruniversity.trigger1
AFTER INSERT
ON jos_dhruprofile
FOR EACH ROW
BEGIN
UPDATE jos_users
SET jos_users.department = NEW.department
WHERE jos_users.id = NEW.uid;
END ||
DELIMITER;
Related
It's probably something stupid but I'm unable to figure it out.The issue is that when i want to perform a check on email_token table,It's not passing.I have a simple query to update the needed data.But every time i get a false on my query.
Here is it:
DELIMITER $$
CREATE TRIGGER email_token_used
BEFORE INSERT
ON email_token FOR EACH ROW
BEGIN
IF(EXISTS(SELECT * FROM email_token WHERE used = 'N' AND usable = 'Y' AND user_id = NEW.user_id)) THEN
UPDATE email_token SET usable='N' WHERE user_id = NEW.user_id;
END IF;
END$$
Here is my table:
Here is the php if needed.It's working without the trigger ,the mail can't be sent since it's not updated in the table:
if(!password_verify($password,$output['password'])){
self::$status = 401;
echo "Pass 1";
}else{
$mail_result = self::$db->query("INSERT INTO email_token(user_id,token,created,expires,used) VALUES('{$output['user_id']}','{$token}',NOW(),DATE_ADD(NOW(), INTERVAL 30 MINUTE),'N')");
if($mail_result){
echo "Pass 2";
$mailer = new Mailer();
$mailer -> send_mail("Token authentication","Token authentication <a href='http://localhost:8888/scripts/functions/collector/login/login_step_2.php?user_id={$token}'>Link</a>",$output['email']);
}else{
self::$status = 409;
echo "Error 1";
}
}
Explanation of the final goal here.
The user logs in,he/she gets a token that is being sent to their email(like a 2 stop verification system).After they get the token,they finish with the login in process.I want to prevent people from having multiple tokens,and if they login several times ,they will get the token on their email.The tokens last for 2min,and i want to update the tokens before to be not valid.
Thanks...
You have run afoul of
A stored function or trigger cannot modify a table that is already
being used (for reading or writing) by the statement that invoked the
function or trigger.
https://dev.mysql.com/doc/refman/5.7/en/stored-program-restrictions.html
I am not sure why you need a trigger here in the first place. It seems to be that you have a situation where INSERT ON DUPLICATE KEY UDPATE can be used. Something like
INSERT INTO email_token(user_id,token,created,expires,used)
VALUES(?,?,NOW(),DATE_ADD(NOW(), INTERVAL 30 MINUTE),'N')
ON DUPLICATE KEY UPDATE usable = 'Y'
Note that you are using string concatenation in your queries. You should be using prepared statements instead.
Based on your comments. It sounds like all you need is a simple INSERT statement (The record needs to be inserted every time). Preceded by an UPDATE statement
UPDATE email_token SET usable='N' WHERE user_id = ?
INSERT INTO email_token(user_id,token,created,expires,used)
VALUES(?,?,NOW(),DATE_ADD(NOW(), INTERVAL 30 MINUTE),'N')
First one invalidates existing records. Second one creates a new record. Still no need for a trigger.
Try it like this:
DELIMITER $$
CREATE TRIGGER email_token_used
BEFORE INSERT
ON email_token FOR EACH ROW
BEGIN
IF(EXISTS(SELECT * FROM email_token WHERE used = 'N' AND usable = 'Y' AND user_id = NEW.user_id)) THEN
BEGIN
UPDATE email_token SET usable='N' WHERE user_id = NEW.user_id;
END;
END IF;
END$$
I am trying to apply a trigger to an existing table and column through PHP.
When executing the PHP code, no error is thrown, but the trigger is not created.
My PHP code is:
//file: migrations.php
// created_at column already defined in a previous migration
//...
$migrations[3]['message'] = "added created_at, updated_at columns on rate table";
$migrations[3]['created'] = "2015-09-05 08:28:00";
$migrations[3]['sql'] = "
DELIMITER |
CREATE TRIGGER rate_created_at BEFORE INSERT ON rate
FOR EACH ROW
BEGIN
SET NEW.created_at = CURRENT_TIMESTAMP;
END |
DELIMITER ;
";
// apply migration
foreach ($migrations as $key => $value) {
// run the migration SQL for the current iteration
$sth = $dbh->prepare( $value['sql'] );
$sth->execute();
}
heres what does work
Copying and pasting the trigger creating SQL into Phpmyadmin
getting rid of the DELIMITER and BEGIN END statements
e.g. if I reduce the SQL to
$migrations[3]['sql'] = "
CREATE TRIGGER rate_created_at BEFORE INSERT ON rate
FOR EACH ROW
SET NEW.created_at = CURRENT_TIMESTAMP;
";
It does run from PHP, problem is I dont believe I can run multiline statements without DELIMITER and BEGIN END.
I have tried
escaping the delimiter character
using different delimiter characters
What can I do to get the PHP to run the SQL with the DELIMITER and BEGIN END statements?
yes, you will have to get rid of those DELIMITER, just have the below code
$migrations[3]['sql'] = "
CREATE TRIGGER rate_created_at BEFORE INSERT ON rate
FOR EACH ROW
BEGIN
SET NEW.created_at = CURRENT_TIMESTAMP;
END;";
See this another post saying same thing PHP: multiple SQL queries in one mysql_query statement
Dummy question: Have the next code in MySQL, but when run it in HeidiSQL, show a sintaxis error near '// CREATE TRIGGER'. I'm not sure if that happen because the trigger doesn't exists. This is the code:
DROP TRIGGER IF EXISTS oportunidades_movimiento_entregado //
CREATE TRIGGER oportunidades_movimiento_entregado;
AFTER INSERT ON historial_entregado
FOR EACH ROW BEGIN
UPDATE oportunidades
SET oportunidades.fechaModificado = NEW.fecha_creacion
WHERE NEW.oportunidad_id = oportunidades.id;
END//
UPDATE
DELIMITER $$
DROP TRIGGER IF EXISTS oportunidades_movimiento_entregado $$
CREATE TRIGGER oportunidades_movimiento_entregado
AFTER INSERT ON historial_entregado
FOR EACH ROW BEGIN
UPDATE oportunidades
SET oportunidades.fechaModificado = NEW.fecha_creacion
WHERE NEW.oportunidad_id = oportunidades.id;
END; $$
DELIMITER //
This works, but now my doubt is... All the code (the DROP and the CREATE) will run everytime, or just the CREATE? I need this because I'm working with 2 tables, in one of them I insert/update the data, after with a trigger insert some of the columns in another table to keep a historial, but when I make a INSERT or UPDATE query in the first table, MySQL display the error #1442
Can't update table oportunidades in stored/function trigger because it's already used by statement which invoked this stored function/trigger.
To get it working, set the delimiter first and reset it after the CREATE TRIGGER statement.
Remove the semicolon at the end of the CREATE TRIGGER line.
This should work:
DELIMITER //
DROP TRIGGER IF EXISTS oportunidades_movimiento_entregado //
CREATE TRIGGER oportunidades_movimiento_entregado -- no trailing semicolon here
AFTER INSERT ON historial_entregado
FOR EACH ROW BEGIN
UPDATE oportunidades
SET oportunidades.fechaModificado = NEW.fecha_creacion
WHERE NEW.oportunidad_id = oportunidades.id;
END//
DELIMITER ;
I am using a licensed software for my website, and of course the engine is encrypted. i have no access and modify to any php code...
It has a feature that i want to change, and i can't modify the php code, since the vendor doesn't allow me to do it...
The only option is to build a separate custom script and run it separately to update fields in database (which is not suitable for my project)
OR to change the values manual in mysql database (again it's not suitable)
There is a third option, and i don't know if it's really possible....
here's the scenario:
The script ads a new row in database whenever the user click on a particular link. That row has 10 fields. last 4 fields are NULL by default and they should stay NULL.
The script insert values in that last 4 fields, and it's unusual, and of course the script is not working properly anymore.
So my question is: Is there any way for me to prevent the insertion of the values for that 4 fields in database ? Can it be locked to NULL ? Can "SET / UPDATE" function be ignored for that fields?
Options:
During insert do not use those columns to insert into.
Write before insert trigger to reset to null those new column values.
Writer before update trigger to reset to null those new column values, based on a where condition.
Update:
If you do not have access to your php code to modify the insert statement, you can only achieve this by defining triggers in database. For this to happen, you should at the least have various privileges like remote connect, create, execute triggers, etc. Unless which you can't do this.
If you have such privileges, you can try on your data table something similar to the following:
before insert trigger as below:
delimiter $$
drop trigger if exists bfimt_omit_colum_data $$
create trigger bfimt_omit_colum_data before insert on my_table
for each row begin
set NEW.col_name_4_to_set_null = NULL,
NEW.col_name_5_to_set_null = NULL,
NEW.col_name_6_to_set_null = NULL;
end;
$$
delimiter ;
Similarly the before update trigger as below:
delimiter $$
drop trigger if exists bfumt_omit_colum_data $$
create trigger bfumt_omit_colum_data before update on my_table
for each row begin
set NEW.col_name_4_to_set_null = NULL,
NEW.col_name_5_to_set_null = NULL,
NEW.col_name_6_to_set_null = NULL;
end;
$$
delimiter ;
You could define a trigger like this:
delimiter //
CREATE TRIGGER set_to_null_bi BEFORE INSERT ON tablename
FOR EACH ROW
BEGIN
SET new.col4 = NULL;
SET new.col5 = NULL;
SET new.col6 = NULL;
END//
delimiter ;
and you could also create a BEFORE UPDATE trigger.
Thanks all for your help, i can't say you codes are not correct, but hey didn't work for me. I manage to solve this by myself, here's the code:
DROP TRIGGER IF EXISTS `trigger_null`;
CREATE DEFINER=`root`#`localhost` TRIGGER `trigger_null` BEFORE INSERT ON `mytable` FOR EACH ROW
SET new.create_action = NULL,
new.col4 = NULL,
new.col5 = NULL,
new.col6 = NULL,
new.col6 = NULL,
new.col7 = NULL,
new.col8 = NULL;
That's all...
Thanks for your reply's !!!
Have a script that I can copy and run in mysql shell just fine, but explodes when attempting the same script in php5 mysql_query. Part of the script:
-- sync shadow with users
drop trigger users_post_insert;
delimiter $$
create trigger users_post_insert after insert on users
for each row
begin
insert into shadow( usr_id ) values( new.usr_id );
end$$
delimiter ;
Raises 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 $$\ncreate trigger users_post_insert after insert
on users\n\tfor each ro' at line 8
Again, have done similar executing script files with PostgresQL and Oracle scripts, so this took me off guard.
Do MySQL scripts need to be passed through a regex before being run, or what?
These are scripts that have been debugged and then applied via php to new schemas.
Might you need to define delimiter first before executing a command, and make sure you dropped an already created trigger (or just use if exists clause) try this
-- sync shadow with users
delimiter $$
drop trigger if exists users_post_insert;$$
create trigger users_post_insert after insert on users
for each row
begin
insert into shadow( usr_id ) values( new.usr_id );
end;$$
delimiter ;
Testing shows mysql_execute cannot accept the DELIMITER command.
To make it work break up your file into chunks, leaving out the DELIMITER lines altogether. For example,
$procs = file_get_contents( '../sql/security.sql' );
$procArr = preg_split( "/delimiter .*\n/", $procs );
Also, remove the set delimiter "$$" from the remaining chunks.
Feed each non-empty chunk into mysql_execute - it's ugly, but it works.