Transaction within a stored procedure always failing - mysql

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);

Related

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

Error executing stored procedure fails

I created a stored procedure in mysql database, which fires multiple insert statemets.
As shown below:
DELIMITER //
DROP PROCEDURE IF EXISTS insert_user_group_info
//
CREATE PROCEDURE insert_group_user_info(groupname varchar(50), groupdesc varchar(100),
createddate varchar(50), createdby varchar(100))
BEGIN
DECLARE RETURN_VAL INT UNSIGNED DEFAULT 0;
DECLARE NEWGROUPID INT UNSIGNED DEFAULT 0;
START TRANSACTION;
Insert into group_tbl (`groupname`,
`groupdesc`,
`groupusers`,
`createdon`,
`createdby`,
`groupstatus`)
values
(groupname,
groupdesc,
'1',
createddate,
createdby,
'1');
SET NEWGROUPID = LAST_INSERT_ID();
INSERT INTO useringroup_tbl
( groupid,
username,
regdate,
joindate,
userstatus,
roleid)
VALUES
( NEWGROUPID,
createdby,
createddate,
createddate,
'1',
'1');
INSERT INTO userinrole_tbl
( username,
groupid,
roleid)
VALUES
(createdby,
NEWGROUPID,
'1');
SET RETURN_VAL = LAST_INSERT_ID();
SELECT RETURN_VAL;
COMMIT;
END//
DELIMITER ;
Schema for tables are as follows
Table 1 group_tbl
CREATE TABLE `group_tbl`
(
`groupid` int(11) NOT NULL auto_increment,
`groupname` varchar(50) NOT NULL,
`groupdesc` varchar(100) NOT NULL,
`groupusers` int(11) NOT NULL,
`createdon` datetime NOT NULL,
`createdby` varchar(50) NOT NULL,
`groupstatus` tinyint(4) NOT NULL,
PRIMARY KEY (`groupid`)
);
Table 2 useringroup_tbl
CREATE TABLE IF NOT EXISTS `useringroup_tbl`
(
`groupid` int(11) NOT NULL,
`username` varchar(50) NOT NULL,
`regdate` datetime NOT NULL,
`joindate` datetime NOT NULL default '0000-00-00 00:00:00',
`userstatus` tinyint(4) NOT NULL,
`closingdate` datetime NOT NULL default '0000-00-00 00:00:00',
`roleid` int(11) NOT NULL default '0',
PRIMARY KEY (`groupid`,`username`)
);
Table 3 userinrole_tbl
CREATE TABLE IF NOT EXISTS `userinrole_tbl`
(
`id` int(11) NOT NULL auto_increment,
`username` varchar(50) NOT NULL,
`groupid` int(11) NOT NULL,
`roleid` int(11) NOT NULL,
PRIMARY KEY (`id`)
);
While executing this procedure by this statement
call insert_group_user_info('test name','test description','2015-05-10 12:10:12','XYZuser')
I get an error
1062 - Duplicate entry '1-XYZuser' for key 1
and each time it the number appended to the username gets incremented
like this
1062 - Duplicate entry '2-XYZuser' for key 1
So please if anybody can give me direction what I am doing wrong,
Thanks in advance.
According to the error you have pasted,
1062 - Duplicate entry '1-XYZuser' - PRIMARY KEY (groupid,username) - It doesn't matter if you truncate the tables or not. You might be inserting the same data again.
You might be using last_insert_id() incorrectly.
Why is there no auto_increment in useringroup_tbl?

Create trigger on insert

I have the following table:
CREATE TABLE `loteria_loterias` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`fecha_ini` datetime NOT NULL,
`fecha_fin` datetime DEFAULT NULL,
`ganador` varchar(60) CHARACTER SET utf8 DEFAULT NULL,
`coste` int(11) NOT NULL,
`premium` int(11) NOT NULL,
`duracion` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `ganador` (`ganador`),
CONSTRAINT `loteria_loterias_ibfk_1` FOREIGN KEY (`ganador`) REFERENCES `tegm_users` (`user_login`)
) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=latin1
Is it posible to create a trigger that fill in 'fecha_fin' with 'fecha_ini + duracion' (duracion is in hours) in every insert?
delimiter |
CREATE TRIGGER `some_name` BEFORE INSERT ON loteria_loterias
FOR EACH ROW BEGIN
SET NEW.fecha_fin = NEW.fecha_ini + interval NEW.duracion hour;
END;
|
delimiter ;

Mysql statement insert, if inserted, insert another

I have the following statement:
INSERT INTO `Properties`(`Id`, `Url`, `BrokerId`, `LastFound`) VALUES
(#Id,#Url,#BrokerId,#LastFound)
ON DUPLICATE KEY UPDATE LastFoundOn = #LastFoundOn;
INSERT INTO `Events`(`Id`, `Type`, `DateTime`, `PropertyId`) VALUES
(#EventId,#EventType,#Now,#Id);
There is a foreign key constraint between Properties.Id and Events.PropertyId. And the Url is unique.
This works - almost. When a recod is not inserted, but updated because of duplicate key (Url), then the insert into event will fail, because the foreign key simply doesn't exist. Like this:
Eg:
exists: 1 | http://test1.com | 2 | 2013-03-13
to insert: 2 | http://test2.com | 2 | 2013-03-14
When trying to insert, it updates instead, because of the unique url. When afterwards trying to insert the event, a foreign key (2) doesn't exist in the Properties table. How can I make an if then statement to handle this scenario?
Something like (?):
INSERT INTO `Properties`(`Id`, `Url`, `BrokerId`, `LastFound`) VALUES
(#Id,#Url,#BrokerId,#LastFound)
ON DUPLICATE KEY UPDATE LastFoundOn = #LastFoundOn;
IF LastInserted = #Id THEN
INSERT INTO `Events`(`Id`, `Type`, `DateTime`, `PropertyId`) VALUES
(#EventId,#EventType,#Now,#Id);
END IF;
UPDATE:
A trigger might be the solution, but I'm struggeling making it work. What's wrong here?
DELIMITER $$
CREATE TRIGGER Event_Submitted_Trigger AFTER INSERT ON Properties
FOR EACH ROW
BEGIN
INSERT INTO Events VALUES(SELECT(UUID()), 'PropertySubmitted', SELECT(NOW()), new.Id);
END$$
I get the following 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 'SELECT(NOW()), new.Id); END$$' at line 4
Best regards,
Søren
UPDATE:
Here is my schema:
CREATE TABLE IF NOT EXISTS `Events` (
`Id` char(36) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
`Type` enum('PropertySubmitted','PropertyChanged','PropertyRemoved') NOT NULL,
`DateTime` datetime NOT NULL,
`Attribute` varchar(128) NOT NULL,
`From` varchar(512) NOT NULL,
`To` varchar(512) NOT NULL,
`PropertyId` char(36) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
PRIMARY KEY (`Id`),
KEY `IX_FK_PropertyEvent` (`PropertyId`),
KEY `DateTimeIndex` (`DateTime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Table structure for table `Properties`
--
CREATE TABLE IF NOT EXISTS `Properties` (
`Id` char(36) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
`Url` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
`Type` varchar(64) NOT NULL,
`ExtractedAddress` varchar(192) NOT NULL,
`ExtractedPostcode` varchar(8) NOT NULL,
`ExtractedCity` varchar(64) NOT NULL,
`StreetName` varchar(128) DEFAULT NULL,
`StreetNumber` varchar(8) DEFAULT NULL,
`Floor` varchar(8) DEFAULT NULL,
`Side` varchar(8) DEFAULT NULL,
`DoorNo` varchar(8) DEFAULT NULL,
`Postcode` int(4) DEFAULT NULL,
`City` varchar(64) DEFAULT NULL,
`Latitude` double DEFAULT NULL,
`Longitude` double DEFAULT NULL,
`ImageUrl` varchar(512) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
`Price` int(8) NOT NULL,
`Payout` int(8) NOT NULL,
`GrossPrice` int(6) NOT NULL,
`NetPrice` int(6) NOT NULL,
`Area` int(5) NOT NULL,
`GroundArea` int(5) NOT NULL,
`Rooms` int(2) NOT NULL,
`Year` int(4) NOT NULL,
`PriceChange` int(11) NOT NULL,
`FirstFoundOn` datetime NOT NULL,
`SubmittedOn` datetime NOT NULL,
`LastFoundOn` datetime NOT NULL,
`FoundAt` varchar(256) DEFAULT NULL,
`Validated` tinyint(1) NOT NULL,
`BrokerId` char(36) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
`Archived` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`Id`),
UNIQUE KEY `Url` (`Url`),
KEY `IX_FK_PropertyBroker` (`BrokerId`),
KEY `UrlIndex` (`Url`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Triggers `Properties`
--
DROP TRIGGER IF EXISTS `Event_Submitted_Trigger`;
DELIMITER //
CREATE TRIGGER `Event_Submitted_Trigger` AFTER INSERT ON `Properties`
FOR EACH ROW BEGIN
INSERT INTO `Events` VALUES(UUID(), 'PropertySubmitted', NOW(), NEW.Id);
END
//
DELIMITER ;
--
-- Constraints for dumped tables
--
--
-- Constraints for table `Events`
--
ALTER TABLE `Events`
ADD CONSTRAINT `Events_ibfk_1` FOREIGN KEY (`PropertyId`) REFERENCES `Properties` (`Id`) ON DELETE CASCADE ON UPDATE CASCADE;
--
-- Constraints for table `Properties`
--
ALTER TABLE `Properties`
ADD CONSTRAINT `Properties_ibfk_2` FOREIGN KEY (`BrokerId`) REFERENCES `Brokers` (`Id`) ON DELETE NO ACTION ON UPDATE NO ACTION;
Assuming the following structure:
CREATE TABLE Properties (
id INT,
url VARCHAR(100),
lastFound DATETIME,
UNIQUE (url)
) ;
CREATE TABLE Events (
id VARCHAR(36),
type VARCHAR(20),
t DATETIME,
propertyId INT
) ;
Here is a working trigger:
DELIMITER $$
CREATE TRIGGER Event_Submitted_Trigger AFTER INSERT ON Properties
FOR EACH ROW BEGIN
INSERT INTO Events VALUES( UUID(), 'PropertySubmitted', NOW(), new.Id);
END $$
DELIMITER ;
See it in action here. Notice the NOW()+SLEEP(1) hack, only meant to delay execution in order to get a significant result (SLEEP() returns 0 if not interrupted).