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)
);
Related
Through phpmyadmin's interface, I created a stored procedure as follows:
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `sp_checkin_create`(IN `userid` INT(10), IN `organizationid` INT(10), IN `checkindate` DATETIME(6), IN `checkoutdate` DATETIME(6), IN `checkinid` INT(10))
NO SQL
Insert Into checkin Values(CheckInID, UserID, OrganizationID, CheckInDate, CheckOutDate) ON DUPLICATE
KEY UPDATE CheckInID=CheckInID, UserID=userid, OrganizationID=organizationid, checkindate=checkindate, CheckOutDate=checkoutdate$$
DELIMITER ;
How do I return LAST_INSERT_ID() from this procedure? I know the use-case of:
SELECT LAST_INSERTED_ID();
But i can't find a way to combine this query in the procedure without getting ambiguous errors.
Any help would be appreciated.
EDIT 1
Create table statement:
DROP TABLE IF EXISTS `checkin`;
CREATE TABLE IF NOT EXISTS `checkin` (
`CheckInID` int(11) NOT NULL AUTO_INCREMENT,
`UserID` int(11) NOT NULL,
`OrganizationID` int(11) DEFAULT NULL,
`CheckInDate` datetime DEFAULT NULL,
`CheckOutDate` datetime(6) NOT NULL,
PRIMARY KEY (`CheckInID`),
UNIQUE KEY `CheckInID` (`CheckInID`)
) ENGINE=MyISAM AUTO_INCREMENT=4407 DEFAULT CHARSET=latin1;
Formally:
DELIMITER $$
CREATE
DEFINER=`root`#`localhost`
PROCEDURE `sp_checkin_create` ( IN `userid` INT(10),
IN `organizationid` INT(10),
IN `checkindate` DATETIME(6),
IN `checkoutdate` DATETIME(6),
IN `checkinid` INT(10),
OUT inserted_id BIGINT )
NO SQL
BEGIN
Insert Into checkin
Values (CheckInID, UserID, OrganizationID, CheckInDate, CheckOutDate)
ON DUPLICATE KEY UPDATE
UserID=userid, OrganizationID=organizationid, checkindate=checkindate, CheckOutDate=checkoutdate;
SELECT LAST_INSERT_ID() INTO inserted_id;
END;
$$
DELIMITER ;
and
CALL sp_checkin_create(123, 456, '2021-01-01', '2021-01-01', 789, #last_inserted_id);
SELECT #last_inserted_id;
Really: LAST_INSERT_ID() is used only when autoincrement generates new value - so it makes no sense in both cases (both new row inserted with AI explicit assigning and ODKU fired).
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...
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
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.
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);