I am seeking a short term solution while I work out why a synchronisation is setting one field wrong in a table
I prepared a trigger and would welcome some comment on it, and any necessary corrections or better strategies.
CREATE TRIGGER urlcorrect AFTER INSERT ON sym_node
FOR EACH ROW BEGIN
IF NEW.sync_url= 'http://wrongaddress' THEN
UPDATE sym_node SET sync_url= "http://123.456.7.89:1234/etc";
END IF;;
END$
delimiter;
thanks
David
Your trigger is wrong in various ways.
First of all, I think you want a BEFORE trigger so that you can fix the row before it gets into your table.
Secondly, this:
UPDATE sym_node SET sync_url= "http://123.456.7.89:1234/etc";
would update every sync_url in the sym_node table and that's not what you want. And I don't think MySQL will let you UPDATE a table inside a trigger on that table (someone correct me if I'm wrong on this please). Also, you should be using single quotes for string literals even though MySQL will let you use double quotes, don't pick up bad habits from MySQL lax behavior. You want to:
set new.sync_url = 'http://123.456.7.89:1234/etc';
Putting all that together, you get this:
delimiter $
create trigger urlcorrect before insert on sym_node
for each row begin
if new.sync_url = 'http://wrongaddress' then
set new.sync_url = 'http://123.456.7.89:1234/etc';
end if;
end;
$
delimiter ;
Related
I'm new to the php mysql developpement, I want to make a trigger to be launched after I insert a row in the evolution table. The trigger must take a value (prixMisDaccord) from another table (inscription) and reduce it value from the evolution column prixAPaye.
Here is what I tried and what I found on Stack Overflow:
DELIMITER $$
CREATE TRIGGER trg_rap
BEFORE INSERT ON evolution FOR EACH ROW
BEGIN
DECLARE pmd float;
-- Check BookingRequest table
SELECT prixMisDaccord
INTO #pmd
FROM inscription
WHERE inscription.idETD= 1;
SET NEW.resteAPaye = #pmd-NEW.prixPaye
WHERE idETD = 1;
END;
$$
DELIMITER `;
'i have a probleme from this line SELECT' - Is not the error I get, I do get an error on the set statement because you cannot apply a where clause to a set..There are other problems with your code and you don't seem to know the difference between user defined variables and declared variables see - How to declare a variable in MySQL? and temporary tables..so #pmd-NEW.prixPaye is just nonsense.
If you want more help read https://stackoverflow.com/help/how-to-ask and provide table definitions,sample data and desired outcome all as text in the question.
create trigger cal_retweet before insert on T
for each row begin
set NEW.retweet_change = NEW.retweet_count - retweet_count where id_str = NEW.id_str
end
SQL said there is syntax error near "where id_str = NEW.id_str"
My table looks like this. Where id_str is a unique identifier for a specific tweet. Since I am inserting 50 tweets from a single user every minute, there would be many same id_str. What I want to look at is the change of retweet_count every minute. tweeted_at is when the user tweeted, created_at is when this data is inserted into my database. I want to generate retweet_change for each new data inserted into the database compared to the same old tweet (into the column retweet_change). How should I write the trigger?
After reading some of your comments I changed my code to :
create trigger cal_retweet before update on T
for each row
begin
set NEW.retweet_change = NEW.retweet_count - OLD.retweet_count;
end;
There is still syntax error
There are several issues with this trigger.
You have some syntax errors. You need proper semicolons to delimit your statements.
You have a WHERE statement that is out of place (and actually not needed). You are acting on only a single row at a time, you don't have to match on the id_str.
In order to factor in a calculation using an existing value from the row, you need access to the OLD keyword. For that, you need a trigger that happens on UPDATE, not INSERT. On INSERT, the retweet_change is simply the same as retweet_count; you could alter your INSERT statement to fix that problem.
You may need to explicitly add a statement delimiter as per the comments below.
So all together, I think this trigger should look like:
DELIMITER //
CREATE TRIGGER cal_retweet BEFORE UPDATE ON T
FOR EACH ROW
BEGIN
SET NEW.retweet_change = NEW.retweet_count - OLD.retweet_count;
END;//
DELIMITER ;
I have searched for all the possible online solutions but I can't figure out the error in this trigger.
CREATE TRIGGER `delete_neat_link`
AFTER DELETE ON `neat_urls`
FOR EACH ROW
BEGIN
DELETE FROM `css_paths`
WHERE `css_paths`.`path_id` = OLD.`neat_link`;
END;
the first error appears at OLD.neat_link
syntax error, unexpected END_OF_INPUT, expecting ';'
and the second one at END;
syntax error, unexpected END
Any help would be appreciable, thanks.
That problem is due to interpreting individual statements. The CREATE TRIGGER statement is as such a single complete statement that must be sent as is to the server. Usually statement borders are recognized by the default delimiter (the semicolon). In case of stored programs however the semicolon is needed to separate inner statements. This would confuse the client as it cannot tell apart what is an inner statement of the stored program or a full statement as it must be sent as a whole to the server.
Hence the DELIMITER statement was introduced which only applies to clients (not the server, the server itself cannot parse this statement). It changes the default delimiter to one of your choice, leading so the client where to look for the statement's end. A typical case hence looks like this:
DELIMITER ;;
CREATE TRIGGER `ins_film` AFTER INSERT ON `film` FOR EACH ROW BEGIN
INSERT INTO film_text (film_id, title, description)
VALUES (new.film_id, new.title, new.description);
END;;
Their is only one statement in the body of the Trigger, so there is no need to use the BEGIN-END compound statement construct. Try this:
CREATE TRIGGER `delete_neat_link`
AFTER DELETE ON `neat_urls`
FOR EACH ROW
DELETE FROM `css_paths`
WHERE `css_paths`.`path_id` = OLD.`neat_link`
another possible solution
DELIMITER $$
CREATE TRIGGER `delete_neat_link`
AFTER DELETE ON `neat_urls`
FOR EACH ROW
BEGIN
DELETE FROM `css_paths`
WHERE `css_paths`.`path_id` = OLD.`neat_link`;
END$$
DELIMITER ;
I'm trying to find a way to check ,before adding a new tuple in a table, if the tuple respect some condition and in case of one of the conditions is not respected do not allow the insert.
I've thought of something like
DELIMITER //
CREATE TRIGGER t BEFORE INSERT ON Table
FOR EACH ROW
CALL CHECK1(…);
CALL CHECK2(…);
CALL CHECK3(…);
//
DELIMITER;
Where check1,check2,check3 are procedures that raise an exception if the NEW.(attributes) that I pass do not respect condition in the inserting table and/or with other tables.
Is this a correct and/or good way to make what I'm trying to do?
What is the best way to do that?
The best way to do it, is to do the data validation using stored procedures, instead of triggers. The trigger strategy is useful if you only want to filter incoming data. If the objective is to cancel an operation entirely when data values are unsuitable, you cannot do this in MySQL using a trigger.
I'm answering to reply(with a comment my answer would be incomprehensible) and to give more details:
I've used 2 strategies to make my goal, here 2 examples
1)if the check is easy
DELIMITER $$
create trigger RV5_1 before insert on Customer
for each row begin
IF(DATEDIFF(CURDATE(),NEW.birthdate)/365<18)
THEN
SIGNAL sqlstate '45006' set message_text = "too young to be a customer";
END IF;
END;
$$
DELIMITER ;
2) if the check is not easy and need cursors, variables etc
DELIMITER $$
create trigger T2 before insert on Table
for each row begin
IF (check1(NEW.[_some_attribute/s_]) or
check2(NEW.[_some_attribute/s_]))
THEN
SIGNAL sqlstate '45002' set message_text = "invalid insert";
END IF;
END;
$$;
DELIMITER ;
where check1 and check2 are stored functions that returns 0 if it's ok or 1 if there are problem with the new tuple.
Maybe someone with the same problem will found this helpful.
New to MySql triggers, just learning.
CREATE TRIGGER MyTrigger
AFTER UPDATE ON MyTable
FOR EACH ROW
BEGIN
IF (new.field1 < 0 or new.field1 > 5) THEN
UPDATE new SET new.field1 = old.field1;
END IF;
END;
The goal is to keep the value of field1 the same, if the update puts it outside the range.
However, instead it sets it to 0. What am I doing wrong? How should this code look?
Here is an example that should hopefully get you started:
DELIMITER ~
CREATE TRIGGER `so_13547992_trigger`
BEFORE UPDATE ON `so_13547992`
FOR EACH ROW BEGIN
IF ( NEW.`field1` < 0 OR NEW.`field1` > 5 ) THEN
SET NEW.`field1` = OLD.`field1`;
END IF;
END;
~
Why would it work better? Well first of all your example trigger is recursive, you can't update the same table in a trigger that was triggered by an update.
Second, the new in your UPDATE statement is not a table name, you need to specify one explicitly.
It doesn't appear to be a legit trigger at all, doesn't your server complain when you try to create it? Can you perhaps show actually SHOW CREATE TRIGGER `your_trigger`; to make sure that it's really created and looks like you pasted it above?
Even if your example would would work, you're trying to do an unconstrained update on all rows of your table, not on the ones you're trying to update, you should have a WHERE clause; again, given that issue one and two are taken care of.