I want to create a Trigger in MySql I did it with SQL Server at school in my class, but for my project, my web hoster only give me MySql DataBase and if I want a SQL Server DB I need to buy a VPS and I can't afford it so i'll do with MySql, I read about MySql Trigger and I saw that they are really more hard to do than SQL Server Trigger.
First here is every article I read about trigger in MySql (To be sure to not be placed as a duplica):
https://www.mysqltutorial.org/mysql-triggers.aspx/
https://www.mysqltutorial.org/create-the-first-trigger-in-mysql.aspx/
https://dev.mysql.com/doc/refman/8.0/en/trigger-syntax.html
https://stackoverflow.com/questions/38745441/how-to-write-trigger-with-multiple-condition-in-mysql
https://stackoverflow.com/questions/33775826/how-to-declare-variables-in-trigger-with-mysql
And here is the SQL Server code I made:
CREATE TRIGGER file_verified_if_admin ON tblOpenSource
AFTER INSERT, UPDATE
AS
BEGIN
DECLARE #source_id INT;
DECLARE #verified TEXT;
DECLARE #client_id INT;
DECLARE c_info CURSOR FOR
SELECT source_id, verified, client_id FROM inserted;
OPEN c_info;
FETCH c_info INTO #source_id,#verified,#client_id;
WHILE (##FETCH_STATUS=0)
BEGIN
IF ((SELECT tblClients.grade FROM tblClients JOIN tblOpenSource ON tblOpenSource.client_id = tblClients.client_id;) == 'admin')
BEGIN
UPDATE tblOpenSource SET verified = 'verified' WHERE source_id = #source_id;
END;
END;
CLOSE c_info;
DEALLOCATE c_info;
END;
Here is what I made with MySql and I still have errors, can someone help me ?
CREATE TRIGGER file_verified_if_admin
AFTER INSERT, UPDATE ON tblOpenSource
FOR EACH ROW
BEGIN
DECLARE client_grade text;
SET #client_grade = (SELECT tblClients.grade FROM tblClients JOIN tblOpenSource ON tblClients.client_id = tblOpenSource.client_id);
IF (#client_grade = 'admin')
UPDATE tblOpenSource SET verified = 'verified' WHERE source_id = NEW.source_id;
END;
It says I have an error near my DELCARE, but I don't understand why, because I heard we don't need an "#" in the declaration.
What it is supposed to do, is to look if the file as been publied by an admin and if yes, it should update the verified column and change the text for verified
Mysql desn_'t allow multiple trigger in one goal you have to define then all.
Maysql needs DELIMITERto know where the trigger starts and ends
Last the IÌF CLause`is in mysql different.
This is the correct syntax, you can change it further by using SELECT INTO
UPDATE #Akina poited out,
that your query will not run, you can't change a row that has triggert the Trigger, mysql will not not allow that, so for your insert trigger, has to be change accordingly.
For the UPDATE Trigger goes teh saem.
DELIMITER //
CREATE TRIGGER file_verified_if_admin
BEFORE INSERT ON tblOpenSource
FOR EACH ROW
BEGIN
SET #client_grade = (SELECT tblClients.grade FROM tblClients JOIN tblOpenSource ON tblClients.client_id = tblOpenSource.client_id);
IF (#client_grade = 'admin') then
SET NEW.verified = 'verified';
END IF;
END//
DELIMITER ;
Related
Please support, I had a stored procedure create in sql server database using a Merge statement inside. I would like to use the same stored procedure in a Mysql database. Unfortunatly it seem the Merge funtion not work in MySql. Anybody can help me to do that ? Below my stored procedure
ALTER PROCEDURE [dbo].[ValiderFacturePharmacie]
#numdossierhospi VARCHAR(50)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
MERGE INTO pharmacie P
USING (SELECT NumDossHp, SUM(TotalProd) AS Total
FROM pharmacie WHERE NumDossHp = #numdossierhospi
GROUP BY NumDossHp) T
ON (P.NumDossHp = T.NumDossHp)
WHEN MATCHED THEN
UPDATE SET
P.TotalPharma = T.Total,
P.Etat ='VALIDE';
END
Thanks you for your answer ! I solved the issue by using this statement below
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `ValiderFacturePharmacie`(IN `numdossierhospi` VARCHAR(30))
NO SQL
UPDATE pharmacies
SET totalpharma = (select SUM(totalprod) from pharmacies where numdosshp = numdossierhospi),
etat = 'FACTURER'
WHERE numdosshp = numdossierhospi$$
DELIMITER ;
It is alomst the same
DELIMITER //
CREATE PROCEDURE ValiderFacturePharmacie (
_numdossierhospi VARCHAR(50))
BEGIN
UPDATE pharmacie P INNER JOIN
(SELECT NumDossHp, SUM(TotalProd) AS Total
FROM pharmacie WHERE NumDossHp = _numdossierhospi
GROUP BY NumDossHp) T
ON (P.NumDossHp = T.NumDossHp)
SET
P.TotalPharma = T.Total,
P.Etat ='VALIDE';
END //
DELIMITER ;
I am programming a trigger (in workbench 8) for mysql that is triggered after an insert to the table, my trigger is as follows:
DELIMITER //
Drop trigger if exists tr_pago;
CREATE TRIGGER tr_pago after insert on pago for each row
BEGIN
declare ultimoidpago int;
declare idcompromisopago int;
declare idunidadrecaudadora int;
declare idboleta int;
Set ultimoidpago = new.IdPago
Set idcompromisopago = (select new.CP_IdCompromisoPago from pago where IdPago = ultimoidpago);
Set idunidadrecaudadora = (select UR_IdUnidadRecaudadora from compromiso_pago where IdCompromisoPago = idcompromisopago);
Set idboleta = (select IdBoleta from boleta where UR_IdUnidadRecaudadora = idunidadrecaudadora );
update pago set new.B_IdBoleta = idboleta where IdPago = ultimoidpago;
END
DELIMITER //
But when making an insert to the payment table, I get the following error:
Error Code: 1442. Can't update table 'pago' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
This is a MySQL restriction in a trigger. Within a trigger, it is not allowed to issue a DML statement (INSERT/UPDATE/DELETE) against any table that is referenced in the statement that caused the trigger to be fired.
Looks like we are wanting to set a column in the inserted row to a value.
This would typically be better handled in a BEFORE INSERT trigger. A BEFORE INSERT trigger is allowed to perform SELECT on other tables.
SET NEW.B_IdBoleta = expr ;
FOLLOWUP
It's not clear what we are intending this trigger to do. But we know it can't issue an UPDATE on pago.
Here's an example of a BEFORE INSERT trigger that attempts to set the value of the b_idboleta column from the result of a query. We add a continue handler to catch the error if the SELECT query doesn't return a row.
DELIMITER //
CREATE TRIGGER tr_pago
BEFORE INSERT ON pago
FOR EACH ROW
BEGIN
DECLARE CONTINUE HANDLER FOR 1329 BEGIN SET NEW.b_idboleta = NULL; END;
SELECT bo.idboleta
INTO NEW.b_idboleta
FROM compromiso_pago cp
JOIN boleta bo
ON bo.ur_idunidadrecaudadora = cp.ur_idunidadrecaudadora
WHERE cp.idcompromisopago = NEW.cp_idcompromisopago
ORDER
BY bo.idboleta
LIMIT 1;
END//
DELIMITER ;
I have created a trigger for my mysql project previously and it was working well. However, I am trying to change this trigger to make suitable for pl-sql(oracle). This is my original code which works in the mysql:
DELIMITER $$
CREATE TRIGGER course_title_delete AFTER DELETE on Course
FOR EACH ROW
BEGIN
DECLARE rownumber INT;
SET rownumber = (SELECT COUNT(*) FROM Course
WHERE Course_code=old.Course_code);
IF rownumber = 0
THEN
DELETE FROM Course_title
WHERE Course_title.Course_code=old.Course_code;
END IF;
END$$
DELIMITER ;
And this one is the same code which I have tried to convert pl-sql format. However it is not working, when I upload as a script and try to run it in apex.
CREATE OR REPLACE TRIGGER course_title_delete
AFTER DELETE ON course
FOR EACH ROW
BEGIN
DECLARE rownumber INT;
SET rownumber = (SELECT COUNT(*) FROM course
WHERE course_code= :old.course_code);
IF rownumber = 0
THEN
DELETE FROM course_title
WHERE course_title.course_code:=:old.course_code;
END IF;
END;
/
At the very least, you have a syntax error in this line:
DELETE FROM course_title
WHERE course_title.course_code:=:old.course_code;
----------------------------------^
That should just be =.
Also, in Oracle, the DECLARE goes before the BEGIN, not after.
Also, in Oracle, this line:
SET rownumber = (SELECT COUNT(*) FROM course
WHERE course_code= :old.course_code);
should be:
SELECT COUNT(*) INTO rownumber
FROM course
WHERE course_code = :old.course_code;
Well, actually, the is the correct syntax for what you are expressing. But, you should be using NOT EXISTS rather than COUNT(*) in both databases.
In both databases, I think you can replace this trigger with a cascading delete foreign key constraint. Also, you can simplify the logic to eliminate the if:
CREATE OR REPLACE TRIGGER course_title_delete
AFTER DELETE ON course
FOR EACH ROW
BEGIN
DELETE FROM course_title
WHERE NOT ExISTS (SELECT 1
FROM course c
WHERE c.course_code = :old.course_code
) AND
course_code = :old.course_code;
END;
This is the database vehicle table's trigger
DROP TRIGGER IF EXISTS InsertVehTrig;
DELIMITER $$
CREATE TRIGGER InsertVehTrig AFTER INSERT
ON Vehicle FOR EACH ROW
SWL_return:
BEGIN
DECLARE Cph CHAR(50);
DECLARE DevID CHAR(12);
DECLARE VehID BIGINT;
DECLARE TmpID BIGINT;
DECLARE DevCount INT;
SET Cph = rtrim(ltrim(NEW.cph));
SET VehID = NEW.ID;
SET DevID = NEW.DevID;
if(VehID is null) then
select count(id) into #DevCount from vehicle where (cph=#Cph) or (DevID=#DevID);
-- 条件:当前的车牌号 或 设备ID
end if;
if (DevCount > 1) then -- 如果记录数,超过1,则认为有重复
-- Rollback not supported in trigger
SET #SWV_Null_Var = 0;
Leave SWL_return;
else
if (DevCount = 1) then
select ID INTO #TmpID from Vehicle where (Vehicle.cph = #Cph) or (Vehicle.DevID = #DevID);
if (TmpID != VehID) then -- --如果增加的车牌号码与数据库中的在相同的,则不允许增加
-- Rollback not supported in trigger
Leave SWL_return;
SET #SWV_Null_Var = 0;
end if;
end if;
end if;
update vehicle set cph = #Cph where ID = #VehID;
END;
Right now i m trying to insert new data row in the vehicle table, but error with this
ERROR 1442: Can't update table 'vehicle' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
SQL Statement:
INSERT INTO `gis_server`.`vehicle` (`TrackerNum`, `cph`, `DevID`, `DevType`) VALUES ('1', 'NR09B00555', 'NR09B00555', '2')
those database are designed by 3 party company,
How do i insert data to vehicle table?
You can achieve this by making two changes to your approach:
Firstly, use a BEFORE trigger rather than an AFTER
Secondly, rather than updating the same table, update the NEW table, setting the column value to the new value before the NEW table hits the table targeted by the INSERT.
For example, replace your UPDATE line with the following:
UPDATE NEW SET cph = Cph;
MySQL doesn't allow you to edit the data in the table on which a trigger is created in that trigger, but you can edit the NEW table to modify the values going into that table.
I got the two following triggers, each one worked alone, but together they don't.
How can I make them to work together? They update different fields in table.
trigger 1:
create trigger wys_sk_u after update on `things`
for each row
begin
UPDATE `current` s
INNER JOIN things u ON s.id_thing = u.id_thing
INNER JOIN dude_base b ON b.id= s.id
SET s.`curr_cash` = u.cash1 * b.cash2/ 100;
end;
$$
trigger 2:
create trigger suma_u after update on `current`
for each row
begin
UPDATE `current`
SET `mysum` = `curr_cash` + `mysum`;
end;
$$
First one should update when cash1 or cash2 updates, and change value of curr_cash.
Second should update when curr_cash updates, and change mysum.
I got following error when I edit table things:
#1442 - Can't update table 'current' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
#edit
added new answear to the question.
What if I want to do something like this:
CREATE TRIGGER total BEFORE UPDATE ON `current` FOR EACH ROW
BEGIN
if new.`new_pay_date` <> old.`new_pay_date`
SET new.`total_cash` = new.`curr_cash` + new.`total_cash`;
end if;
END;
$$
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 'SET new.`total_cash` = new.`curr_cash` + new.`total_cash`; end if;' at line 4
This was working without
if new.`new_pay_date` <> old.`new_pay_date`
end if;
But I need to check this, and only update with date change.
current table:
curr_cash
new_pay_date
id_person
id_thing
total_cash
Anyone can help me with this one?
The problem is in the second trigger. Try to use BEFORE UPDATE trigger to change field value using SET statement -
CREATE TRIGGER suma_u BEFORE UPDATE ON `current` FOR EACH ROW
BEGIN
SET new.`mysum` = new.`curr_cash` + new.`mysum`;
END;
It is not possible to update a table for for which the trigger is created in the trigger. There is locking mechanism on MySQL so that you can't update the row of the same table triggered the trigger, it can cause recursive call to the trigger and infinite loop.