MySQL Trigger Insert Before Not Firing - mysql

I'm trying to add a trigger for auditing to initialize a datetime field on an insert. Does anyone see what might be causing this trigger to not fire???
USE example;
CREATE TABLE USERS (
ID INT UNSIGNED NOT NULL AUTO_INCREMENT,
FULLNAME VARCHAR(128) NOT NULL,
`PASSWORD` CHAR(88) NOT NULL,
EMAIL VARCHAR(128) NOT NULL,
FLAGS TINYINT UNSIGNED DEFAULT 0,
CREATED DATETIME,
UPDATED TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE INDEX(EMAIL),
PRIMARY KEY( ID )
);
DELIMITER $$;
CREATE TRIGGER USER_T BEFORE INSERT ON USERS FOR EACH ROW
BEGIN
SET NEW.CREATED = CURRENT_TIMESTAMP();
END;$$
DELIMITER ;
INSERT INTO USERS(FULLNAME, `PASSWORD`, EMAIL) VALUES('Admin', 'sQnzu7wkTrgkQZF+0G1hi5AI3Qmzvv0bXgc5THBqi7mAsdd4Xll27ASbRt9fEyavWi6m0QP9B8lThf+rDKy8hg==', 'root#localhost');

It looks like you are using the ; as a delimiter here
SET NEW.CREATED = CURRENT_TIMESTAMP();
END;$$
DELIMITER ;
Try this:
DELIMITER $$;
CREATE TRIGGER USER_T BEFORE INSERT ON USERS FOR EACH ROW
BEGIN
SET NEW.CREATED = CURRENT_TIMESTAMP();
END $$
DELIMITER ;

Related

Trigger doesn't get created, despite no errors being detected

Table:
create table produto
(
referencia varchar(3) primary key,
descricao varchar(50) unique,
estoque int not null default 0,
preco_normal decimal(10,2),
preco_desconto decimal(10,2)
);
Trigger (I tried creating it without a delimiter to no avail as well):
delimiter //
create trigger desconto before insert
on produto
for each row
begin
if new.estoque < 5 then
set new.preco_desconto = new.preco_normal * 0.90;
else
set new.preco_desconto = new.preco_normal;
end if;
end//
delimiter ;
The trigger result:
But when I use drop trigger if exists desconto;
The output says Trigger does not exist
Any ideas on how to solve this?

Mysql #1442 - Can't update table 'stock' in stored function/trigger

My triger It works normally but if i use procedur in the insert I'm getting the error
1442 - Can't update table 'stock' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
bu if i use manuel insert into table panier Normal inserted does not show me the error :'(
i use it like that :
call temps;
call stock_panier(94,19,'tranche');
call panier_ins(22547153,6185,null,now());
my triger :
DELIMITER $$
CREATE TRIGGER Stock_cal BEFORE INSERT on panier
FOR EACH ROW BEGIN
DECLARE is_exist INT;
DECLARE is_exist1 INT;
DECLARE is_exist2 INT;
set is_exist = (select stock.qte_res_s from stock WHERE stock.code_s=new.code_s);
set is_exist1 = new.qte_p;
set is_exist2 = new.qte_p;
if (is_exist<is_exist1) OR (is_exist2<1) THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '✘: Opération a été refusée.';
ELSE
UPDATE stock SET qte_res_s=qte_res_s-new.qte_p,qte_sor_s=qte_sor_s+new.qte_p WHERE new.code_s=stock.code_s ;
END if;
END$$
DELIMITER ;
my table temperer :
CREATE PROCEDURE `temps`()
BEGIN
call virifier_table_exist('panier_tm');
if (#table_exists)=0 THEN
CREATE TEMPORARY TABLE `panier_tm` (
`N_p` bigint(20) DEFAULT Null,
`N` bigint(20) DEFAULT null,
`Code_barr` varchar(100) DEFAULT NULL,
`Référence` varchar(40) DEFAULT NULL,
`Désignation` varchar(40) DEFAULT NULL,
`Prix_HT` varchar(20) DEFAULT NULL,
`Fournisseur` varchar(30) DEFAULT NULL,
`Magasin` varchar(10) DEFAULT NULL,
`Qte_Vent` varchar(5) DEFAULT NULL,
`code_s` bigint(20) DEFAULT NULL,
`code_d` bigint(20) DEFAULT NULL,
tva_p varchar(5) DEFAULT Null,
type_ver varchar(15) DEFAULT null);
SET #row_number:=0;
else
DROP TEMPORARY TABLE `panier_tm`;
CREATE TEMPORARY TABLE `panier_tm` (
`N_p` bigint(20) DEFAULT Null,
`N` bigint(20) DEFAULT null,
`Code_barr` varchar(100) DEFAULT NULL,
`Référence` varchar(40) DEFAULT NULL,
`Désignation` varchar(40) DEFAULT NULL,
`Prix_HT` varchar(20) DEFAULT NULL,
`Fournisseur` varchar(30) DEFAULT NULL,
`Magasin` varchar(10) DEFAULT NULL,
`Qte_Vent` varchar(5) DEFAULT NULL,
`code_s` bigint(20) DEFAULT NULL,
`code_d` bigint(20) DEFAULT NULL,
tva_p varchar(5) DEFAULT Null,
type_ver varchar(15) DEFAULT null);
SET #row_number:=0;
end if;
END$$
DELIMITER ;
my procedure :
drop PROCEDURE if EXISTS panier_ins ;
DELIMITER $$
CREATE PROCEDURE panier_ins (in code_cccp varchar(30), code_cl1 bigint(20),N_p1 bigint(20),dat date)
BEGIN
DECLARE code_faa varchar(20);
DECLARE n_p2 bigint(20);
START TRANSACTION;
if (SELECT COUNT(Qte_Vent) from panier_tm tm2,stock WHERE tm2.code_s=stock.code_s and tm2.Qte_Vent>stock.qte_res_s and not EXISTS (select 1 from panier_vu vu2 where tm2.N_p=vu2.code_p and tm2.code_s=vu2.code_s ))>0 THEN
SELECT "Veuillez vous assurer que le stock est terminé" AS message ;
ELSE
set #count_n_p=(select COUNT(n_p) from panier_tm where n_p=n_p1);
set #n_p=(select n_p from panier_tm where n_p=n_p1);
if (#n_p) is null OR (#count_n_p)=0 THEN
SET #n_p2=(SELECT MIN(t1.code_p+1) as id FROM panier t1 LEFT JOIN panier t2 On t1.code_p+1=t2.code_p Where t2.code_cl IS NULL);
set #n_p2=if(#n_p2 = null,1,#n_p2);
INSERT INTO `panier`(`code_p`, `n_p`, `code_s`, `code_cl`, `type_ver_p`, `date_p`, `qte_p`, `prix_p`, `tva_p`) SELECT #n_p2,tm1.n,stock.code_s,code_cl1,type_ver,dat,qte_vent,prix_ht,tva_p FROM `preduit`,`stock`,`panier_tm` tm1 WHERE preduit.code_pr=stock.code_pr and tm1.code_s=stock.code_s and NOT EXISTS (select 1 from panier_vu vu1 where tm1.N_p=vu1.code_p and tm1.code_s=vu1.code_s);
update panier_tm set N_p=#n_p2;
set code_faa=(SELECT MIN(SUBSTRING(t1.code_fa, 6, length(t1.code_fa)-5)+1) as id FROM facture t1 LEFT JOIN facture t2 On SUBSTRING(t1.code_fa, 6, length(t1.code_fa)-5)+1=SUBSTRING(t2.code_fa, 6, length(t2.code_fa)-5) Where t2.code_fa IS NULL);
set code_faa= CONCAT( DATE_FORMAT(now(),"%Y"),"/",code_faa) ;
INSERT INTO `facture`(`autot`, `code_fa`, `code_ccp`, `code_cl`, `code_p`, `date_fa`, `type_ver`) VALUES (null,code_faa,code_cccp,code_cl1,#n_p2,now(),typ);
COMMIT ;
ELSE
START TRANSACTION;
INSERT INTO `panier`(`code_p`, `n_p`, `code_s`, `code_cl`, `type_ver_p`, `date_p`, `qte_p`, `prix_p`, `tva_p`) SELECT tm1.n_p,tm1.n,stock.code_s,code_cl1,type_ver,dat,qte_vent,prix_ht,tva_p FROM `preduit`,`stock`,`panier_tm` tm1 WHERE preduit.code_pr=stock.code_pr and tm1.code_s=stock.code_s and NOT EXISTS (select 1 from panier_vu vu1 where tm1.N_p=vu1.code_p and tm1.code_s=vu1.code_s);
DELETE b FROM `panier` b LEFT JOIN panier_tm f ON f.code_s = b.code_s and b.code_p=f.N_p WHERE code_p=n_p1 and f.N_p is null;
UPDATE `panier` p1,panier_tm tms SET p1.`n_p`=tms.N_p,p1.`qte_p`=tms.Qte_Vent,p1.`prix_p`=tms.Prix_HT,`tva_p`=tva1 WHERE p1.code_p=N_p1 and p1.code_s=tms.code_s;
COMMIT ;
END if;
END IF;
END$$
DELIMITER ;
Your problem are the two inserts into panier that depend on stock, while you have an on insert-trigger on panier that modifies the table stock that the insert into panier depends on:
INSERT INTO `panier`(`code_p`, ...) SELECT #n_p2,tm1.n,stock.code_s, ...
FROM `preduit`,`stock`,`panier_tm` tm1 WHERE reduit.code_pr=stock.code_pr ...
INSERT INTO `panier`(`code_p`, ...) SELECT tm1.n_p,tm1.n,stock.code_s, ...
FROM `preduit`,`stock`,`panier_tm` tm1 WHERE preduit.code_pr=stock.code_pr ...
They both have the structure
INSERT INTO panier (...) SELECT ... FROM stock ...
which is not allowed if you have an insert trigger on panier which modifies stock. These inserts are the statement which invoked this stored function/trigger in which you can't update table 'stock'. MySQL is for technical reasons not able to do this.
The straight forward technical workaround for this is to create a temporary table in which you store the result of your SELECT ..., and then insert into panier from that temporary table, e.g. something like
create temporary table tmp (...);
insert into tmp (...) select ... from stock ...;
insert into panier (...) select ... from tmp;
drop table tmp;
The insert-trigger now doesn't modify any dependent tables anymore, since you only select from tmp.
In your procedure, this would look like
create temporary table tmp (code_p bigint(20), n_p bigint(20),
..., tva_p varchar(5));
if (#n_p) is null OR (#count_n_p)=0 THEN
...
insert into tmp (code_p, n_p, ...)
SELECT #n_p2,tm1.n,stock.code_s, ...
FROM `preduit`,`stock`,`panier_tm` tm1 WHERE reduit.code_pr=stock.code_pr ...
insert into panier (code_p, n_p, ...) select code_p, n_p, ... from tmp;
...
else
...
insert into tmp (code_p, n_p, ...)
SELECT tm1.n_p,tm1.n,stock.code_s, ...
FROM `preduit`,`stock`,`panier_tm` tm1 WHERE preduit.code_pr=stock.code_pr ...
insert into panier (code_p, n_p, ...) select code_p, n_p, ... from tmp;
...
end if;
drop table tmp;
You can of course create the temporary table in your procedure temps.
It is also usually possible to redesign your procedure, triggers or logic so you do not need this, but that would probably be a larger endeavour.
And you should verify if that is actually the logic you want to apply, e.g. if you want to decide on the current state of stock which rows to insert, freeze this state (by putting it into the tmp-table) and then run the insert independently of how the stock-table changed during those inserts (e.g. if you would have inserted the 2nd row if you would have known what the first row changed in stock). I didn't check what your code is supposed to do, so this may or may not apply here, and may or may not be a problem here, but circular dependendies (and the error you get here because of it) can sometimes be a sign for an underlying problem.

insert is failing because of my trigger mysql

I have a problem with my trigger code.
After I wrote my trigger I wrote Insert to test the trigger. But my Insert gets error as
Error Code:1109. Unknown table employees in field list.
If I put the insert before the trigger-everything works perfect. But I want this Insert to test the trigger.
drop database if exists kontrolno;
create database kontrolno;
use kontrolno;
CREATE TABLE departments(
id TINYINT UNSIGNED PRIMARY KEY,
name CHAR(12) NOT NULL,
min_salary SMALLINT UNSIGNED NOT NULL,
max_salary SMALLINT UNSIGNED NOT NULL
) ENGINE=InnoDB;
CREATE TABLE employees(
id SMALLINT UNSIGNED PRIMARY KEY,
name VARCHAR(255) NOT NULL,
salary SMALLINT UNSIGNED NOT NULL,
department_id TINYINT UNSIGNED,
constraint FOREIGN KEY (department_id)
REFERENCES departments(id)
) ENGINE=InnoDB;
insert into departments(id,name,min_salary,max_salary)
values(1,"qa", 800,2000),
(2,"jd",1200,3500);
DROP TRIGGER if exists checkSalary;
delimiter |
create trigger checkSalary before Insert on employees
for each row
begin
if(employees.salary>max_salary OR employees.salary<min_salary)
then signal sqlstate '45000' set MESSAGE_TEXT="the salary is not valide";
end if;
end;
|
delimiter ;
insert into employees(id,name,salary,department_id)
values(1,"ivan", 200,1);
You had mistakes in your trigger code.
The trigger code should be:
DROP TRIGGER if exists checkSalary;
delimiter |
create trigger checkSalary before Insert on employees
for each row
begin
if(new.salary>(select max_salary from departments where id=new.department_id)
OR
new.salary<(select min_salary from departments where id=new.department_id) )
then signal sqlstate '45000' set MESSAGE_TEXT="the salary is not valid";
end if;
end;
|
delimiter ;

Need help writing the case statement - MySQL Cursor

I created two columns in student table for my database. I now need to create a cursor for the student table. I need to make use of the input parameters for start and end student Id’s to filter the results in the cursor query.
I also need to open the cursor created and check if the student has an email assigned or not. If the email is not assigned I need to update the email column to have an email assigned to the student.
Finally to why I want help:
I cannot figure out how I would write the case statements for this cursor. I have tried to think of a good way to do this and not succeeded. Please help!!
DELIMITER $
DROP PROCEDURE IF EXISTS CURSOR_DEMO$
CREATE PROCEDURE CURSOR_DEMO(start_student_id INT
,end_student_id INT
)
BEGIN
DECLARE l_table_name VARCHAR(50);
DECLARE iam_done INT DEFAULT 0;
DECLARE l_sql_stmt VARCHAR(5000);
SET #l_sql_stmt='ALTER TABLE STUDENT ADD EMAIL VARCHAR';
SELECT #l_sql_stmt;
prepare stmt from #l_sql_stmt;
execute stmt;
SET #l_sql_stmt='ALTER TABLE STUDENT ADD PHONE int(10)';
SELECT #l_sql_stmt;
prepare stmt from #l_sql_stmt;
execute stmt;
DECLARE TBL_CUR CURSOR FOR
SELECT EMAIL FROM STUDENT.TABLES WHERE TABLE_SCHEMA='MYSQLDB';
BEGIN
DECLARE CONTINUE HANDLER FOR NOT FOUND SET IAM_DONE=1;
OPEN TBL_CUR;
tbl_loop:LOOP
FETCH tbl_cur INTO l_table_name;
IF IAM_DONE = 1 THEN
LEAVE tbl_loop;
END IF;
CASE WHEN l_table_name = 'STUDENT' THEN
ELSE BEGIN END;
END CASE;
END LOOP tbl_loop;
CLOSE TBL_CUR;
END;
END$
DELIMITER ;
Is this the kind of thing you need?
/*
drop table student;
delimiter $$
CREATE TABLE `student` (
`id` int(11) NOT NULL ,
`name` char(1) NOT NULL,
`email` varchar(1),
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8$$
drop table email;
delimiter $$
CREATE TABLE `email` (
`id` int(11) NOT NULL ,
`type` varchar(8) NOT NULL,
`person_id` int,
`email` varchar(1),
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8$$
;
*/
DELIMITER $
DROP PROCEDURE IF EXISTS CURSOR_DEMO$
CREATE PROCEDURE CURSOR_DEMO(start_student_id INT
,end_student_id INT)
BEGIN
declare email_person_id int;
declare email_address varchar(50);
DECLARE done INT DEFAULT 0;
DECLARE CUR CURSOR FOR
SELECT person_id,email FROM sandbox.email where type = 'student';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1;
OPEN CUR;
cur_loop:LOOP
IF done = 1 THEN
LEAVE cur_loop;
END IF;
FETCH CUR INTO email_person_id,email_address;
update student
set email = email_address
where id = email_person_id
and email is null
;
END LOOP cur_loop;
CLOSE CUR;
commit;
END$
DELIMITER ;
truncate table student;
insert into student
values
(1,'A','1'),
(2,'B','1'),
(3,'C',null),
(4,'D',null),
(5,'E',null),
(6,'G',null),
(7,'F',null)
;
truncate table email;
insert into email
values
(1,'student',1,'a'),
(2,'student',2,'b'),
(3,'faculty',7,'z'),
(4,'student',3,'c')
;
select * from student;
call cursor_demo(1,10);
select * from student;

Mysql trigger #1064 error

I'm trying to write a trigger to solve innodb auto_increment problem. I want to make orderID is auto_increment however innodb does not allow me. Here is ORDER table
CREATE TABLE IF NOT EXISTS `ORDER` (
`placeID` INT UNSIGNED NOT NULL,
`orderID` INT UNSIGNED NOT NULL,
`userID` INT UNSIGNED NOT NULL ,
`tableNum` SMALLINT NOT NULL,
`orderStatus` TINYINT NOT NULL,
`orderDate` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`placeID`,`orderID`),
FOREIGN KEY (`userID`) REFERENCES `USER` (`userID`),
FOREIGN KEY (`placeID`) REFERENCES `PLACE` (`placeID`))
ENGINE=InnoDB;
Here is the trigger
delimiter $$
DROP TRIGGER /*!50032 IF EXISTS */ `ORDER_TRIGGER` $$
CREATE TRIGGER `ORDER_TRIGGER` BEFORE INSERT ON `ORDER`
FOR EACH ROW
BEGIN
DECLARE orderID INT UNSIGNED;
SELECT MAX(`orderID`) INTO orderID FROM `ORDER` WHERE `placeID` = NEW.placeID;
IF orderID IS NULL THEN
orderID = 1;
END IF;
SET NEW.orderID = orderID+1;
END;
$$
delimiter;
When I execute this script I get this 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 '= 1;
END IF;
SET NEW.orderID = orderID+1;
END' at line 7
Can anybody help me? I looked at google but I can't find accurate solution.
I found my mistake. This is right code.
delimiter $$
DROP TRIGGER /*!50032 IF EXISTS */ `ORDER_TRIGGER` $$
CREATE TRIGGER `ORDER_TRIGGER` BEFORE INSERT ON `ORDER`
FOR EACH ROW
BEGIN
DECLARE orderID INT UNSIGNED;
SELECT MAX(`ORDER`.`orderID`) AS ID INTO orderID FROM `ORDER` WHERE `ORDER`.`placeID` = NEW.placeID;
IF orderID IS NULL THEN
SET orderID = 0;
END IF;
SET NEW.orderID = orderID+1;
END;
$$