Tiggers , before inserted trigger? - mysql

I have two tables , table (files) and table (Hashes) i want to create a procedure that inserts new (file) wich will add a ( Hash ) if not exists and then inserts its ( ID ) in the ( files) table , if exists select the (ID) and insert it , and i also must use ( before insert on files trigger ) i ried but it either gives me an CONSTRAINT error OR Insert in hash and no file inserted.
CREATE TABLE `Hashes` (
`ID` int(255) unsigned NOT NULL AUTO_INCREMENT,
`Hash` varchar(255) NOT NULL,
`Counter` int(255) NOT NULL DEFAULT '1',
PRIMARY KEY (`ID`),
UNIQUE KEY `Hash` (`Hash`)
)
and
CREATE TABLE `Files` (
`ID` int(255) unsigned NOT NULL AUTO_INCREMENT,
`Name` varchar(255) NOT NULL,
`ParentPath` varchar(255) DEFAULT NULL,
`Size` double NOT NULL,
`Date` date NOT NULL,
`ParentID` int(255) unsigned NOT NULL DEFAULT '0',
`HashID` int(255) unsigned DEFAULT NULL,
PRIMARY KEY (`ID`),
KEY `fk_Hash_ID` (`HashID`),
CONSTRAINT `fk_Hash_ID` FOREIGN KEY (`HashID`) REFERENCES `hashes` (`ID`)
)
////////
CREATE PROCEDURE SP_Files_Insert
(
parmName VARCHAR(255),
parmParentPath VARCHAR(255),
parmSize DOUBLE,
parmDate DATE,
parmParentID INTEGER,
parmHash VARCHAR(255)
)
BEGIN
INSERT INTO Files( Name, ParentPath, Size, Date, ParentID, HashID)
VALUES(parmName, parmParentPath, parmSize, parmDate, parmParentID, LAST_INSERT_ID());
END;
////////////
CREATE TRIGGER TR_Insert_File BEFORE INSERT ON Files
FOR EACH ROW
BEGIN
INSERT INTO Hash( Hash, Counter)
VALUE( parmHash, 1)
ON DUPLICATE KEY UPDATE ID = LAST_INSERT_ID(ID), Counter = Counter + 1;
END;

use delimiter in your trigger like below that will work for you
delimiter \\
CREATE TRIGGER TR_Insert_File BEFORE INSERT ON Files
FOR EACH ROW
BEGIN
INSERT INTO Hash( Hash, Counter)
VALUE( parmHash, 1)
ON DUPLICATE KEY UPDATE ID = LAST_INSERT_ID(ID), Counter = Counter + 1;
END\\
delimiter ;

Related

Transaction within a stored procedure always failing

I've created a stored procedure via phpmyadmin which carries out a transaction as follows:
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
SELECT -1;
ROLLBACK;
END;
START TRANSACTION;
INSERT INTO review(reviewer_name, reviewer_gender, house_id, rental_date_from, rental_date_to, house_rating,house_comment) VALUES (name, gender, house_id, date_from,date_to, clean_rating,comments);
UPDATE rental SET reviewed = 1 WHERE renter_id = renter_id AND house_id = house_id AND date_from = dateFrom AND date_to = dateTo ;
COMMIT;
SELECT 1;
END
The parameters were set like this:
parameters to the stored procedure
Each time I execute the stored procedure with valid values via phpmyadmin, I get -1 returned and no tables are affected. Not quite sure what's wrong here.
Edit: Added some info
SHOW CREATE PROCEDURE sp_save_review:
| sp_save_review | NO_ZERO_IN_DATE,NO_ZERO_DATE,NO_ENGINE_SUBSTITUTION | CREATE DEFINER=`root`#`localhost` PROCEDURE `sp_save_review`(IN `name` VARCHAR(200), IN `gender` VARCHAR(50), IN `house_id` INT(11), IN `date_from` DATE, IN `date_to` DATE, IN `clean_rating` FLOAT, IN `comments` VARCHAR(1000), IN `renter_id` INT(11))
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
SELECT -1;
ROLLBACK;
END;
START TRANSACTION;
INSERT INTO review(reviewer_name, reviewer_gender, house_id, rental_date_from, rental_date_to, house_rating,house_comment) VALUES (name, gender, house_id, date_from,date_to, clean_rating,comments);
UPDATE rental SET reviewed = 1 WHERE renter_id = renter_id AND house_id = house_id AND date_from = dateFrom AND date_to = dateTo ;
COMMIT;
SELECT 1;
SHOW CREATE TABLE review:
| review | CREATE TABLE `review` (
`review_id` int(11) NOT NULL AUTO_INCREMENT,
`reviewer_name` varchar(200) CHARACTER SET utf32 NOT NULL,
`reviewer_gender` varchar(50) CHARACTER SET utf32 NOT NULL,
`house_id` int(11) NOT NULL,
`rental_date_from` date NOT NULL,
`rental_date_to` date NOT NULL,
`house_rating` float NOT NULL,
`house_comment` varchar(1000) CHARACTER SET utf32 NOT NULL,
`flagged` tinyint(1) NOT NULL DEFAULT 0,
`banned` tinyint(1) NOT NULL DEFAULT 0,
PRIMARY KEY (`review_id`),
KEY `house_id` (`house_id`),
CONSTRAINT `review_ibfk_1` FOREIGN KEY (`house_id`) REFERENCES `rental` (`house_id`)
) ENGINE=InnoDB AUTO_INCREMENT=70 DEFAULT CHARSET=latin1 COLLATE=latin1_bin |
SHOW CREATE TABLE rental:
| rental | CREATE TABLE `rental` (
`renter_id` int(11) NOT NULL,
`house_id` int(11) NOT NULL,
`date_from` date NOT NULL,
`date_to` date NOT NULL,
`price` double NOT NULL,
`reviewed` tinyint(1) NOT NULL DEFAULT 0,
PRIMARY KEY (`renter_id`,`house_id`,`date_from`),
KEY `house_id` (`house_id`),
CONSTRAINT `rental_ibfk_1` FOREIGN KEY (`house_id`) REFERENCES `house` (`house_id`),
CONSTRAINT `rental_ibfk_2` FOREIGN KEY (`renter_id`) REFERENCES `renter` (`renter_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_bin |
You seem to have got into a fankle with your naming try this
DROP TABLE IF EXISTS REVIEW;
DROP TABLE IF EXISTS RENTAL;
CREATE TABLE `rental` (
`renter_id` int(11) NOT NULL,
`house_id` int(11) NOT NULL,
`date_from` date NOT NULL,
`date_to` date NOT NULL,
`price` double NOT NULL,
`reviewed` tinyint(1) NOT NULL DEFAULT 0,
PRIMARY KEY (`renter_id`,`house_id`,`date_from`),
KEY `house_id` (`house_id`) #,
#CONSTRAINT `rental_ibfk_1` FOREIGN KEY (`house_id`) REFERENCES `house` (`house_id`),
#CONSTRAINT `rental_ibfk_2` FOREIGN KEY (`renter_id`) REFERENCES `renter` (`renter_id`)
) ;
CREATE TABLE `review` (
`review_id` int(11) NOT NULL AUTO_INCREMENT,
`reviewer_name` varchar(200) CHARACTER SET utf32 NOT NULL,
`reviewer_gender` varchar(50) CHARACTER SET utf32 NOT NULL,
`house_id` int(11) NOT NULL,
`rental_date_from` date NOT NULL,
`rental_date_to` date NOT NULL,
`house_rating` float NOT NULL,
`house_comment` varchar(1000) CHARACTER SET utf32 NOT NULL,
`flagged` tinyint(1) NOT NULL DEFAULT 0,
`banned` tinyint(1) NOT NULL DEFAULT 0,
PRIMARY KEY (`review_id`),
KEY `house_id` (`house_id`),
CONSTRAINT `review_ibfk_1` FOREIGN KEY (`house_id`) REFERENCES `rental` (`house_id`)
) ;
DROP PROCEDURE IF EXISTS P;
DELIMITER $$
CREATE PROCEDURE P(IN `Pname` VARCHAR(200), IN `Pgender` VARCHAR(50), IN `Phouse_id` INT(11),
IN `Pdate_from` DATE, IN `Pdate_to` DATE, IN `Pclean_rating` FLOAT,
IN `Pcomments` VARCHAR(1000), IN `Prenter_id` INT(11))
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
SELECT -1;
ROLLBACK;
END;
START TRANSACTION;
INSERT INTO review(reviewer_name, reviewer_gender, house_id, rental_date_from, rental_date_to, house_rating,house_comment)
VALUES (Pname, Pgender, Phouse_id, Pdate_from,Pdate_to, Pclean_rating,Pcomments);
UPDATE rental
SET reviewed = 1
WHERE renter_id = Prenter_id AND house_id = Phouse_id AND date_from = Pdate_From AND date_to = Pdate_To ;
COMMIT;
SELECT 1;
END $$
DELIMITER ;
INSERT INTO RENTAL( `renter_id`, `house_id` , `date_from` , `date_to` , `price`, `reviewed` )
VALUES (1,1,'2022-01-01','2022-01-01',10,0);
CALL P('AAA','F',1,'2022-01-01','2022-01-01',1,'BBB',1);

Create a table in a trigger and compare it

i have 4 tables and i want to create a trigger that it declares a table and store it all in that table so it can be compared latter.
CREATE TABLE IF NOT EXISTS `inventory` (
`id_product` INT(4) ZEROFILL NOT NULL AUTO_INCREMENT,
`model` varchar(45) NOT NULL,
`price_new` FLOAT DEFAULT '0',
`launch_date` DATE NOT NULL,
`stock` INT DEFAULT '0',
PRIMARY KEY (`id_product`));
CREATE TABLE IF NOT EXISTS `order` (
`id_order` INT(4) ZEROFILL NOT NULL AUTO_INCREMENT,
`id_customer` INT(6) ZEROFILL NOT NULL,
`subtotal` FLOAT DEFAULT '0',
`discount` float DEFAULT '0',
`tax_rate` float DEFAULT '0.23',
`total` float DEFAULT '0',
`date` DATETIME DEFAULT NOW(),
PRIMARY KEY (`id_order`),
CONSTRAINT `fk_order_1`
FOREIGN KEY (`id_customer`)
REFERENCES `iSAVE`.`customer` (`id_customer`)
ON DELETE RESTRICT
ON UPDATE CASCADE);
CREATE TABLE IF NOT EXISTS `order_item` (
`id_order_item` INT(4) ZEROFILL NOT NULL AUTO_INCREMENT PRIMARY KEY,
`id_product` INT(4) ZEROFILL NOT NULL,
`id_order` INT(4) ZEROFILL NOT NULL,
`quantity` INT DEFAULT NULL,
FOREIGN KEY (`id_product`) REFERENCES `iSAVE`.`inventory` (`id_product`),
FOREIGN KEY (`id_order`) REFERENCES `iSAVE`.`order` (`id_order`)
);
CREATE TABLE IF NOT EXISTS `transaction` (
`id_transaction` INT(4) ZEROFILL NOT NULL AUTO_INCREMENT PRIMARY KEY,
`id_order` INT(4) ZEROFILL NOT NULL,
`status` char(20) default 'Not completed',
FOREIGN KEY (`id_order`) REFERENCES `iSAVE`.`order` (`id_order`)
);
In here are the tables that im using. But now i have a trigger that after insert on orders it inserts on transactions. My objective now its to create a trigger that generates a table that takes order and order item and store id_product id_order and quantity so it can be used to after update on transaction the stock is changed on the respective items on tabel inventory.
This is the trigger that i have so far but i cant use it because i dont rly know how to declare a table in mysql:
delimiter $$
CREATE TRIGGER trigg1 after update on `transaction` for each row
BEGIN
declare #item TABLE(
id_order int,
id_product int,
quantity int);
update inventory i join #item it using (id_product)
set i.stock = i.stock - it.quantity
where it.id_order = new.id_order;
end $$
delimiter ;
You can't you have to use a temporaRY TABLE
delimiter $$
CREATE TRIGGER trigg1 after update on `transaction` for each row
BEGIN
CREATE TEMPORARY TABLE tbl1(
id_order int,
id_product int,
quantity int);
update inventory i join tbl1 it using (id_product)
set i.stock = i.stock - it.quantity
where it.id_order = new.id_order;
DROP TEMPORARY TABLE tbl1;
end $$
delimiter ;
But usually you make a temporaray atble with a select
CREATE TEMPORARY TABLE tbl1
SELECT id_order ,
id_product ,
quantity
FROM ORDERS

Update inventory after transaction

CREATE TABLE IF NOT EXISTS `inventory` (
`id_product` INT(4) ZEROFILL NOT NULL AUTO_INCREMENT,
`model` varchar(45) NOT NULL,
`price_new` FLOAT DEFAULT '0',
sell_price float,
`condition1` varchar(45) NOT NULL,
`launch_date` DATE NOT NULL,
`stock` INT DEFAULT '0',
PRIMARY KEY (`id_product`));
CREATE TABLE IF NOT EXISTS `order` (
`id_order` INT(4) ZEROFILL NOT NULL AUTO_INCREMENT,
`id_customer` INT(6) ZEROFILL NOT NULL,
`subtotal` FLOAT DEFAULT '0',
`discount` float DEFAULT '0',
`tax_rate` float DEFAULT '0.23',
`total` float DEFAULT '0',
`date` DATETIME DEFAULT NOW(),
PRIMARY KEY (`id_order`),
CONSTRAINT `fk_order_1`
FOREIGN KEY (`id_customer`)
REFERENCES `iSAVE`.`customer` (`id_customer`)
ON DELETE RESTRICT
ON UPDATE CASCADE);
CREATE TABLE IF NOT EXISTS `transaction` (
`id_transaction` INT(4) ZEROFILL NOT NULL AUTO_INCREMENT PRIMARY KEY,
`id_order`INT(4) ZEROFILL NOT NULL,
`status` char(20) default 'Not completed',
FOREIGN KEY (`id_order`) REFERENCES `iSAVE`.`order` (`id_order`)
);
CREATE TABLE IF NOT EXISTS `order_item` (
`id_order_item` INT(4) ZEROFILL NOT NULL AUTO_INCREMENT PRIMARY KEY,
`id_product` INT(4) ZEROFILL NOT NULL,
`id_order` INT(4) ZEROFILL NOT NULL,
`quantity` INT DEFAULT NULL,
FOREIGN KEY (`id_product`) REFERENCES `iSAVE`.`inventory` (`id_product`),
FOREIGN KEY (`id_order`) REFERENCES `iSAVE`.`order` (`id_order`)
);
I have those tables and my objective is after i update transactions to completed it goes to my inventory table and update the stock. The items that it should update are the items that i choose in order items.
For now i have this peace of code but its not working ...
delimiter $
create trigger update_stock
after update on `transaction`
for each row
begin
if new.`status` = 'Completed' THEN
update inventory
set inventory.stock = inventory.stock - new.quantity
where inventory.id_product = new.id_product;
end if;
End $$
delimiter ;
Edited trigger:
delimiter $$
CREATE TRIGGER trigg1 after update on `transaction` for each row
BEGIN
UPDATE `inventory`
SET stock = (SELECT stock - new.quantity FROM order_item WHERE order_item.id_product = inventory.id_product limit 1);
end $$
delimiter ;
You seem to need an extra join to get the quantity from order_item:
update inventory i join
order_item oi
using (id_product)
set i.stock = i.stock - oi.quantity
where oi.id_order = new.id_order;

Error Code: 1109. Unknown table 'evrz.account' in field list

I am trying to create a trigger, but I get this error:
Error Code: 1109. Unknown table 'evrz.account' in field list
I tried to execute this:
INSERT INTO `record` (`record`.account_id) VALUES (289688082)
This is my trigger:
CREATE DEFINER=`root`#`localhost` TRIGGER `evrz`.`record_BEFORE_INSERT` BEFORE INSERT ON `record` FOR EACH ROW
BEGIN
IF `evrz`.`account`.`status` ='OUT' in (
SELECT `evrz`.`account`.`status`
FROM `evrz`.`account`
WHERE (account_id = NEW.account_id)
)THEN
UPDATE `evrz`.`account` SET `evrz`.`account`.`status` = 'IN' WHERE (`evrz`.`account`.`account_id` = NEW.account_id);
END IF;
IF `evrz`.`account`.`status` ='IN' in (
SELECT `evrz`.`account`.`status`
FROM `evrz`.`account`
WHERE (account_id = NEW.account_id)
)THEN
UPDATE `evrz`.`account` SET `status` = 'OUT' WHERE (`evrz`.`account`.`account_id` = NEW.account_id);
END IF;
END
These are my tables:
CREATE TABLE `employee` (
`employee_id` int(10) NOT NULL AUTO_INCREMENT,
`name` varchar(45) NOT NULL,
`lastname` varchar(45) NOT NULL,
`address` varchar(45) NOT NULL,
`phone` varchar(45) NOT NULL,
`mail` varchar(45) NOT NULL,
`created_at` TIMESTAMP(0) NOT NULL DEFAULT 'CURRENT_TIMESTAMP()',
PRIMARY KEY (`employee_id`)
);
CREATE TABLE `account` (
`account_id` int(10) NOT NULL AUTO_INCREMENT,
`status` enum('IN','OUT') NOT NULL DEFAULT ''OUT'',
`employee_id` int(10) NOT NULL UNIQUE,
PRIMARY KEY (`account_id`)
);
CREATE TABLE `record` (
`record_id` int(10) NOT NULL AUTO_INCREMENT,
`account_id` int(10) NOT NULL,
`creted_at` TIMESTAMP(0) NOT NULL DEFAULT 'CURRENT_TIMESTAMP()',
PRIMARY KEY (`record_id`)
);
ALTER TABLE `account` ADD CONSTRAINT `account_fk0` FOREIGN KEY (`employee_id`) REFERENCES `employee`(`employee_id`);
ALTER TABLE `record` ADD CONSTRAINT `record_fk0` FOREIGN KEY (`account_id`) REFERENCES `account`(`account_id`);
I am trying to make that when an employee logs in to a database, his stsus will be changed.
The IF statement can only refer to the row that's being inserted, using NEW.columnName to refer to a column in the new row.
When you're updating another table, use the IF function (or a CASE expression) in the value, and it can refer to the existing value in the row being updated.
CREATE DEFINER=`root`#`localhost` TRIGGER `evrz`.`record_BEFORE_INSERT` BEFORE INSERT ON `record` FOR EACH ROW
BEGIN
UPDATE evrz.account
SET status = IF(status = 'OUT', 'IN', 'OUT')
WHERE account_id = NEW.account_id;
END

Auto increment Id value increased by 1 after insert trigger

I have 3 tables as below:
CREATE TABLE `user_dummy` (
`user_id` INT(11) NOT NULL AUTO_INCREMENT,
`user_name` VARCHAR(50) NOT NULL,
`user_email` VARCHAR(100) NOT NULL,
PRIMARY KEY (`user_id`)
)
ENGINE=InnoDB
;
CREATE TABLE `user_role` (
`user_role_id` INT(11) NOT NULL AUTO_INCREMENT,
`user_role_name` VARCHAR(255) NULL DEFAULT NULL,
PRIMARY KEY (`user_role_id`)
)
ENGINE=InnoDB
;
CREATE TABLE `user` (
`user_seq` INT(11) NOT NULL AUTO_INCREMENT,
`user_id` INT(11) NOT NULL,
`user_name` VARCHAR(50) NOT NULL,
`user_email` VARCHAR(100) NOT NULL,
`user_role_id` INT(11) NOT NULL,
PRIMARY KEY (`user_seq`),
INDEX `FKh2wc2dtfdo8maylne7mgubowq` (`user_role_id`),
CONSTRAINT `FKh2wc2dtfdo8maylne7mgubowq` FOREIGN KEY (`user_role_id`) REFERENCES `user_role` (`user_role_id`) ON UPDATE CASCADE ON DELETE CASCADE
)
ENGINE=InnoDB
;
I have created after insert trigger on user table.
i.e., when I insert 1 record into user_dummy table, it will insert records into table user table with all mappings of user_role.
trigger:
CREATE TRIGGER `user_dummy_after_insert` AFTER INSERT ON `user_dummy` FOR EACH ROW BEGIN
INSERT INTO user(user_id, user_name, user_email, user_role_id)
SELECT NEW.user_id, NEW.user_name, NEW.user_email, user_role_id
FROM user_role;
END
Above trigger is able to insert records into user table but the auto_increment value is incremented by 1 after each user_role record.
If you observe user_seq 3 is missing. And after inserting 4 records, auto_increment value set by trigger as 7.
How to fix this ?
Just an alternative: Better you could use the count function to count the total existing records and then increase it by one and assign according as. If you are interested to preserve the insertion sequence.