MySQL, phpMyAdmin: after insert trigger not firing - mysql

I have defined the following trigger on my database in phpMyAdmin:
It's a very simple trigger where I just insert a record into the history table after an insert in the item table:
insert into history values(null, new.Id, new.LocationId, new.LocationId, new.PersonId, new.PersonId, date(now()))
However, the trigger is not firing (and it worked correctly when I tested it in MySQL Workbench).
Edit 1:
The trigger fires when I define it with some dummy values, like this:
insert into history values(null, 1, 1, 1, 1, 1, date(now()))
Edit 2:
The history table is written into when I define the trigger with dummy values (see edit 1). But the most recently added entry's ID is 11 (ID is auto_increment), even though the last entry before that had ID = 3. My point is that they are not consecutive, but rather as if there were entries in between but were deleted for some reason...
Edit 3:
Here is the DDL for item and history tables:
create table Item
(
Id int not null auto_increment primary key,
InventoryNumber int not null unique,
ItemStatus varchar(20) not null,
ItemType varchar(30) not null,
ItemName varchar(100) not null,
PurchaseDate date not null,
PurchaseValue decimal(12,4) not null,
Amortization decimal(12,4) not null,
LocationId int not null,
PersonId int not null,
foreign key(PersonId) references Person(Id),
foreign key(LocationId) references Location(Id)
);
create table History
(
Id int not null auto_increment primary key,
ItemId int not null,
OldLocationId int not null,
NewLocationId int not null,
OldPersonId int not null,
NewPersonId int not null,
DateOfChange date not null,
foreign key(ItemId) references Item(Id),
foreign key(OldLocationId) references Location(Id),
foreign key(NewLocationId) references Location(Id),
foreign key(OldPersonId) references Person(Id),
foreign key(NewPersonId) references Person(Id)
);
and the trigger (which I think is irrelevant since I didn't import the trigger via a script, I defined it using phpMyAdmin's GUI):
DELIMITER //
CREATE TRIGGER historyTriggerInsert AFTER INSERT ON Item
FOR EACH ROW
BEGIN
insert into History values(null, new.Id, new.LocationId, new.LocationId, new.PersonId, new.PersonId, date(now()));
END;//
DELIMITER ;
And here is another thing I found out: when I add an entry to item using my Yii web application, the entry is visible in the item table in phpMA, but the trigger inserts nothing into the history table. However, when I add an entry to item directly in phpMA, the trigger also creates an entry in history i.e. it works correctly.
Also, when I define the trigger with those dummy values but only leave new.Id, like this:
insert into history values(null, new.Id, 1, 1, 1, 1, date(now()))
it also doesn't work. This and the incrementing ID leads me to a conclusion that the trigger is fired, tries to insert into history, but for some reason gets an invalid new.Id value.

Related

Trigger dows not let me insert data in mysql

i am trying to get used to triggers. I created a small database and a trigger. When i go to insert something in ship category it does not let me do it.If i drop the trigger with the same commend i can insert values at the table. I get this error: #1048 - Column 'IMO' cannot be null
My trigger code is:
/*ship insert*/
DELIMITER //
CREATE TRIGGER `ship_insert_logs`
AFTER INSERT ON `ship`
FOR EACH ROW
BEGIN
DECLARE ship_IMO INTEGER;
SET ship_IMO=new.IMO;
INSERT INTO ship_logs VALUES (null, concat('A new row is inserted with IMO ', ship_IMO, 'at',
date_format(now(), '%d-%m-%y %h:%i:%s %p')));
END //
DELIMITER ;
and ship table is:
CREATE TABLE ship(
department_id INTEGER NOT NULL,
IMO BIGINT PRIMARY KEY NOT NULL,
Latitude DOUBLE PRECISION NOT NULL,
Longitude DOUBLE PRECISION NOT NULL,
current_speed DOUBLE PRECISION NOT NULL,
heading VARCHAR (30),
status VARCHAR(30),
FOREIGN KEY(department_id) REFERENCES department (department_id) ON UPDATE CASCADE
);
while ship_logs table is:
CREATE TABLE ship_logs(
IMO BIGINT PRIMARY KEY NOT NULL,
audit_description VARCHAR(500)
);

MySQL BEFORE INSERT TRIGGER is not affecting first record entry

I am trying to calculate the differential column of the score table upon inserting into a MySQL 8.0 database using a before trigger. The calculation uses the coursetee table as well. The trigger works fine on all but the first record in the table, which doesn't get updated. Is there something that I am missing? All relevant code is below.
CREATE TABLE coursetee (
teeID INT UNSIGNED AUTO_INCREMENT,
tee_name VARCHAR(20) NOT NULL,
course_rating DECIMAL(3,1) NOT NULL,
slope_rating INT UNSIGNED NOT NULL,
par INT UNSIGNED,
CONSTRAINT pk_coursetee PRIMARY KEY (teeID),
CREATE TABLE score (
roundID INT UNSIGNED AUTO_INCREMENT,
teeID INT UNSIGNED,
round_score INT UNSIGNED NOT NULL,
round_date DATETIME NOT NULL,
entry_date DATETIME DEFAULT NOW() NOT NULL,
differential DECIMAL(3,1),
CONSTRAINT pk_score PRIMARY KEY (roundID),
CONSTRAINT fk_score_coursetee FOREIGN KEY (teeID) REFERENCES coursetee(teeID));
DELIMITER $$
CREATE TRIGGER calculate_differential
BEFORE INSERT ON score
FOR EACH ROW
BEGIN
SET NEW.differential = (SELECT ROUND((113/ct.slope_rating)*(NEW.round_score-ct.course_rating),1)
FROM score, coursetee as ct
WHERE NEW.teeID = ct.teeID AND differential IS NULL);
END$$
DELIMITER ;
INSERT INTO coursetee
(courseID,tee_name,course_rating,slope_rating,par)
VALUES
(1,'Back',74.7,143,72),
(1,'Middle',72.6,136,72),
(1,'Front',71.3,132,72),
(2,'Back',76.8,155,72),
(2,'Middle',73.9,146,72),
(2,'Front',65.3,125,72);
INSERT INTO score
(playerID,teeID,round_score,round_date)
VALUES
(1,2,79,'2019-07-25');
INSERT INTO score
(playerID,teeID,round_score,round_date)
VALUES
(2,2,80,'2019-07-25');
INSERT INTO score
(playerID,teeID,round_score,round_date)
VALUES
(1,2,77,'2019-08-06');
The query returns:
image of query not returning calculated record for row 1
CREATE TRIGGER calculate_differential
BEFORE INSERT
ON score
FOR EACH ROW
SET NEW.differential = ( SELECT ROUND((113/ct.slope_rating)*(NEW.round_score-ct.course_rating),1)
FROM coursetee ct
WHERE NEW.teeID = ct.teeID);
fiddle
The problem was in using score table as a source of the subquery. And the hope that differential BEFORE inserting the first record will give anything except NOT FOUND. And testing the field of the record BEFORE INSERT for NULL makes no sense.
My assumption is about the FROM clause of the differential query in the trigger. i'd suggest you to try change the order of the tables -
FROM score, coursetee as ct
to
FROM coursetee as ct, score
Seems like its trying to extract nothing for the first insert...

MySQL create after insert trigger fails foreign key constraint

I have 3 tables:
create table users (
id int auto_increment primary key,
first_name varchar(40) not null,
last_name varchar(40) not null,
email varchar(40) not null,
password varchar(40) not null,
deleted tinyint(1) not null default 0
) engine = InnoDB;
create table comments (
id int auto_increment primary key,
task_id int not null,
foreign key fk_comment_task(task_id) references tasks(id),
user int not null,
foreign key fk_comment_user(user) references users(id),
comment varchar(1000) not null,
comment_date date not null,
viewed tinyint(1) not null default 0,
deleted tinyint(1) not null default 0
) engine = InnoDB;
create table viewed_comments (
id int auto_increment primary key,
comment int not null,
foreign key fk_viewed_comment(comment) references comments(id),
viewer int not null,
foreign key fk_viewed_viewer(viewer) references users(id),
unread tinyint(1) not null default 0,
deleted tinyint(1) not null default 0
) engine = InnoDB;
I made a trigger that creates rows in viewed_comments for every user in the users table that is not the user that submitted the comment:
delimiter |
create trigger ins_views after insert on comments
for each row
begin
DECLARE finished INT DEFAULT 0;
DECLARE id INT DEFAULT 0;
DECLARE currentId CURSOR FOR SELECT id FROM users WHERE id != NEW.user;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;
OPEN currentId;
update_views_loop: LOOP
FETCH currentId INTO id;
IF finished = 1 THEN LEAVE update_views_loop; END IF;
INSERT INTO viewed_comments (comment, viewer) VALUES (NEW.id, id);
END LOOP update_views_loop;
CLOSE currentId;
END;
|
delimiter ;
The problem is that when I try to insert a comment such as
insert into comments (task_id, user, comment, comment_date) values (24, 6, 'test', '2018-3-5');
It fails saying the 'Cannot add or update a child row: a foreign key constraint fails (viewed_comments, CONSTRAINT fk_viewed_viewer FOREIGN KEY (viewer) REFERENCES users (id)). When I change the trigger on the insert line to the following it works to a degree:
INSERT INTO viewed_comments (comment, viewer) VALUES (NEW.id, 6);
On this sample set I have 3 users, and on the viewed_comments table I get 3 new rows, instead of 2. I'm not sure how to troubleshoot this in MySQL or how to print the variables to see the values as it happens. It seems on the cursor line New keyword is disregarded resulting in 3 rows instead of 2. But, then it has a value on the insert statement, but the cursor doesn't have any values. I am using MariaDB 10.4.11 How do I fix this?

Cannot create trigger

I am just want to create after insert trigger to insert a new row in history table. Why am I getting an error when I run the query?
orders
create table orders
(
id int auto_increment
primary key,
id_user int not null,
picture_name varchar(100) not null,
time date not null,
constraint FK_USER
foreign key (id_user) references stef.users (id)
)
;
create index FK_USER_idx
on orders (id_user)
;
history
create table history
(
id int auto_increment
primary key,
id_order int not null,
id_action int not null,
time date not null,
constraint FK_ORDER
foreign key (id_order) references stef.orders (id),
constraint FK_ACTION
foreign key (id_action) references stef.actions (id)
)
;
create index FK_ORDER_idx
on history (id_order)
;
create index FK_ACTION_idx
on history (id_action)
;
my trigger...
CREATE TRIGGER orders_AFTER_INSERT
AFTER INSERT ON stef.orders
FOR EACH ROW
BEGIN
INSERT INTO history('id_order', 'id_action', 'time')
VALUES (NEW.id, 1, NOW());
END;
I am just want to create after insert trigger to insert a new row in history table. Why am I getting an error when I run the query?
Try this
DELIMITER $$
CREATE TRIGGER orders_AFTER_INSERT
AFTER INSERT ON stef.orders
FOR EACH ROW
BEGIN
INSERT INTO history(`id_order`, `id_action`, `time`)
VALUES (NEW.id, 1, NOW());
END$$
DELIMITER ;
You need to temporarily override the delimiter so MySQL can differentiate between the end of a statement within the body of a trigger (or procedure, or function) and the end of the body.
Edit: Single quotes (') are only ever used to denote string values, for field names use the ` (or in some configurations the ")
CREATE TRIGGER orders_AFTER_INSERT
AFTER INSERT ON stef.orders
FOR EACH ROW
BEGIN
INSERT INTO stef.history()
VALUES (null, NEW.id, 1, NOW());
END

inserting values from arrays in mysql

I have multiple user_roles. Each user_role has multiple privileges and each privileges has multiple values. I need to create a procedure with user_role_name,description,priviliges_fk(array),values(arrayofstring) as inputs.
This is the procedure I have written.
DELIMITER $$
DROP PROCEDURE IF EXISTS `save_role`$$
CREATE DEFINER=`event_admin`#`%` PROCEDURE `save_role`(IN p_role_name INT,
IN p_description INT,
IN p_privilege_fk INT(),
IN p_values VARCHAR(1000)
)
BEGIN
DECLARE i int default 0;
DECLARE V_ROLE_FK int;
DECLARE counter INT DEFAULT 0;
INSERT INTO ROLE (ROLE_NAME,DESCRIPTION) VALUES(p_role_name,p_description);
SELECT ROLE_PK INTO V_ROLE_FK FROM ROLE WHERE ROLE_NAME=p_role_name AND DESCRIPTION=p_description;
simple_loop:LOOP
SET counter = counter + 1;
INSERT INTO ROLE_PRIVILEGE_BRIDGE (ROLE_FK,PRIVILEGE_FK,VALUE) VALUES(V_ROLE_FK,p_privilege_fk(i),p_values);
END LOOP simple_loop;
END;
You can't. There are two workarounds that would work
Call the procedure one time per element in the array
Concatenate the array elements into one string separated by something (ie |, ;, :) and then split that string internally in the procedure.
I would go with the first alternative. It's cleaner, easier to understand and easier to test.
I'd suggest you to use AUTO_INCREMENT option for primary keys, it will help to work with them. Then use auto-incremented primary key values to insert new rows into a child table - one by one, not using array as a string parameter.
For example (data is simplified):
CREATE TABLE ROLE(
ID INT(11) NOT NULL AUTO_INCREMENT,
ROLE_NAME INT,
DESCRIPTION INT,
PRIMARY KEY (ID)
)
ENGINE = INNODB;
CREATE TABLE ROLE_PRIVILEGE_BRIDGE(
ID INT(11) NOT NULL AUTO_INCREMENT,
PRIVILEGE_FK INT(11) DEFAULT NULL,
VALUE INT(11) DEFAULT NULL,
PRIMARY KEY (ID),
CONSTRAINT FK FOREIGN KEY (PRIVILEGE_FK) REFERENCES ROLE (ID)
)
ENGINE = INNODB;
INSERT INTO ROLE(ROLE_NAME, DESCRIPTION) VALUES(1, 1);
SET #new_id = LAST_INSERT_ID();
INSERT INTO ROLE_PRIVILEGE_BRIDGE(PRIVILEGE_FK, VALUE) VALUES (#new_id, 1);
INSERT INTO ROLE_PRIVILEGE_BRIDGE(PRIVILEGE_FK, VALUE) VALUES (#new_id, 2);
INSERT INTO ROLE_PRIVILEGE_BRIDGE(PRIVILEGE_FK, VALUE) VALUES (#new_id, 3);