how to use the msql trigger to update a column - mysql

As illustrated in the image below, I want the column grand_score to be automatically calculated when values for paper_score and final_score are inserted.
This is what i have tried:
DELIMITER $$
CREATE TRIGGER myTableAutoSum
BEFORE INSERT ON `stumgr_scores` FOR EACH ROW
BEGIN
SET NEW.grand_score= NEW.paper_score + NEW.final_score;
END;
$$
DELIMITER ;
Issue
when i input values for paper_score and final_score, the table does not get updated (i mean grand_score)
Image

I don't immediately see what is wrong with your trigger, unless one of the values happens to be NULL. That is easily fixed using COALESCE():
SET NEW.grand_score = COALESCE(NEW.paper_score, 0) + COALESCE(NEW.final_score, 0);
I question the use of triggers for this purpose. You also need a trigger for UPDATE, in case the values change that way.
Isn't simpler to remove grand_total from the table and use a view?
create view v_stumgr_scores as
select ss.*,
COALESCE(ss.paper_score, 0) + COALESCE(ss.final_score, 0) as grand_score
from stumgr_scores ss;
Or, better yet, in the most recent versions of MySQL, just use a generated column. That is the best solution -- it even allows you to create an index on the value.

Related

MySQL trigger error doesn't work because it needs a value from another table column

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.

I want to write trigger for restricing numeric values insertion

I want to write trigger for restricting user to insert numeric values and special characters in Name field of column.
CREATE TRIGGER trig_check BEFORE
INSERT ON tempuser
FOR EACH ROW
BEGIN
IF :new.firstname NOT LIKE '%[0-9]%'
THEN
dbms_output.put_line('INSERT ONLY ALPHABETS');
END IF;
END;
/
As #a_horse_with_no_name pointed out, better to add a check constraint like the one below :
alter table TAB
add constraint CHK_NAME_WITHOUT_NUMBER
check (not regexp_like(name,'[0-9]+'));
of course after clearing the data which contain numbers. To accomplish this aim, the following DML statement may be used before the above DDL :
update tab
set name = regexp_replace(name,'[0-9]+','');

SQL where syntax error with trigger

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 ;

MySql - trigger doesn't run as expected

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.

set range for column

I'm using in my database, many fields of a certain range, like:
CREATE TABLE figures (
deg FLOAT,-- between 0 and pi
prc FLOAT,-- between 0 and 1
.......
);
CREATE TRIGGER filter1 BEFORE UPDATE ON figures FOR EACH ROW SET
NEW.deg=IF(NEW.deg>3.1415926 OR NEW.deg<0, OLD.deg,NEW.deg),
NEW.prc=IF(NEW.prc>1 OR NEW.prc<0, OLD.prc,NEW.prc),
..........;
CREATE TRIGGER filter2 BEFORE INSERT ON figures FOR EACH ROW SET
NEW.deg=IF(NEW.deg>3.1415926 OR NEW.deg<0, NULL,NEW.deg),
NEW.prc=IF(NEW.prc>1 OR NEW.prc<0, NULL,NEW.prc),
.........;
Is there any way to write it more clearly ?
Something like:
--CREATE PROCEDURE/FUNCTION between()..................
CREATE TABLE figures (
deg FLOAT between(0,3.1415),
prc FLOAT between(0,1),
.......
At least, I don't want to write every filter twice. (ON INSERT,ON UPDATE)
prior to MySQL 8.0.16
Triggers are the best solution
Re:check constraints...
'The CHECK clause is parsed but ignored by all storage engines.'.....
'The reason for accepting but ignoring syntax clauses is for compatibility, to
make it easier to port code from other SQL servers, and to run applications
that create tables with references. '
lifted directly from: http://dev.mysql.com/doc/refman/5.1/en/alter-table.html
From MySQL 8.0.16 though they now work as you would expect
CREATE TABLE figures (
deg FLOAT,
prc FLOAT,
CONSTRAINT `deg_min` CHECK ((`deg` > 0)),
CONSTRAINT `deg_max` CHECK ((`deg` < 3.1415)),
CONSTRAINT `prc_min` CHECK ((`prc` > 0)),
CONSTRAINT `prc_max` CHECK ((`prc` < 1))
)
At least, I don't want to write every filter twice. (ON INSERT,ON UPDATE)
You can write a stored function and call that in your trigger.
DELIMITER $$
CREATE FUNCTION check_deg (degree FLOAT, olddegree FLOAT) RETURNS FLOAT
BEGIN
DECLARE result FLOAT;
result = IF(degree>3.1415926 OR degree <0, olddegree,degree);
RETURN result;
END$$
DELIMITER ;
That way you have one point where the limits are defined and if anything changes you only have to change the boundaries in one place.
The best solution is to use a CHECK() constraint, but MySQL doesn't support CHECK() constraints. (MySQL parses them, then ignores them.)
In some cases, you can replace a CHECK() constraint with a foreign key reference to a table that contains all the valid values. Floating-point numbers are not a good candidate for that kind of solution, though.
That leaves triggers. In your case, your best bet is to use a trigger that calls a stored function.
I have a unfinished idea :
CREATE PROCEDURE check_constraint (table VARCHAR,field VARCHAR,condition VARCHAR)
BEGIN
SET #update_trigger = CONCAT ("
IF EXIST TRIGGER check_constraint_",table,"_",field,"
BEGIN /*I don't know yet what to do*/ END
ELSE /*IF TRIGGER DONT EXIST*/
BEGIN
CREATE TRIGGER check_constraint_",table,"_",field,"
BEFORE UPDATE ON ",table," FOR EACH ROW SET
NEW.",field,"=IF("condition, ", OLD.",field,",NEW.",field,");
END
");
PREPARE update_trigger FROM #update_trigger;
EXECUTE update_trigger;
DEALLOCATE PREPARE update_trigger;
SET #insert_trigger = ..............................
END
After we have a completed function, we can just call it during creation of the database:
CALL check_constraint("table","field","NEW.field<34567");