Error executing stored procedure fails - mysql

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?

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

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

Mysql Procedure INSERT (Already I looked at other answers)

in mysql I have two tables: produto and dim_produto.
CREATE TABLE `produto` (
`IdProduto` int(11) NOT NULL AUTO_INCREMENT,
`Ativo` char(1) DEFAULT 'S',
`CodPro` int(4) NOT NULL,
`CodCat` int(4) NOT NULL,
`DesPro` varchar(45) NOT NULL,
`CodMar` int(3) NOT NULL,
`CodSab` int(3) NOT NULL,
`QtdCaixa` int(2) NOT NULL,
`Transmitido` char(1) DEFAULT 'N',
PRIMARY KEY (`IdProduto`,`CodPro`),
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
--
CREATE TABLE `dim_produto` (
`CodPro` int(4) NOT NULL,
`Ativo` char(1) DEFAULT NULL,
`CodCat` int(4) DEFAULT NULL,
`Despro` varchar(45) DEFAULT NULL,
`IdInc` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`CodPro`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
I'm trying to make a procedure that makes a select product in the table and enter the dim_produto table.
DELIMITER |
CREATE PROCEDURE dimProduto (codpro int (4), ativo char (1), codcat int (4), despro varchar (45))
BEGIN
insert into dim_produto (codpro, ativo, codcat, despro) (select codpro, ativo, codcat, despro from produto where transmitido = 'N');
END |
If I do this insert the way it is in the procedure, it works perfectly.
How do you call the procedure when I insert it in the select table dim_produto?
And how can I call it?
Grateful.

Using Auto-Increment value in MYSQL Before Insert Trigger?

The users table:
CREATE TABLE `users` (
`id` int(8) unsigned NOT NULL AUTO_INCREMENT,
`email` varchar(45) DEFAULT NULL,
`username` varchar(16) DEFAULT NULL,
`salt` varchar(16) DEFAULT NULL,
`password` varchar(128) DEFAULT NULL,
`lastlogin` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`joined` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`loggedin` tinyint(1) unsigned NOT NULL DEFAULT '0',
`sessionkey` varchar(60) DEFAULT NULL,
`verifycode` varchar(16) DEFAULT NULL,
`verified` tinyint(1) unsigned NOT NULL DEFAULT '0',
`banned` tinyint(1) unsigned NOT NULL DEFAULT '0',
`locked` tinyint(1) unsigned NOT NULL DEFAULT '0',
`ip_address` varchar(45) DEFAULT NULL,
`failedattempts` tinyint(1) unsigned NOT NULL DEFAULT '0',
`unlocktime` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=latin1;
The user_records table:
CREATE TABLE `user_records` (
`id` int(8) unsigned NOT NULL AUTO_INCREMENT,
`userid` int(8) unsigned DEFAULT NULL,
`action` varchar(100) DEFAULT NULL,
`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;
The before insert trigger on the users table:
USE `gknet`;
DELIMITER $$
CREATE DEFINER=`root`#`localhost` TRIGGER `before_create_user` BEFORE INSERT ON `users` FOR EACH ROW BEGIN
INSERT INTO user_records (action, userid, timestamp)
VALUES ('CREATED', ID, NOW() );
END
Basically, my problem here is that on the trigger when I try to put in the id of the user that's automatically assigned by MySQL (PK, NN, Auto-Increment), it just puts in 0 for userid on the user_records table. How would I do it so it would select the id that the user is being assigned by SQL, and put it in as userid on the records entry (where the ID is right after 'CREATED')?
Also, if you see any other optimizations that could be made on the tables, feel free to let me know :D
OP's comment:
How would I do it before, thou?
You can find current auto_increment value that is to be assigned to a new record.
And use the same in the before trigger as a parent user id for user_records table.
You have to query information_schema.tables table to find the value.
Example:
use `gknet`;
delimiter $$
drop trigger if exists before_create_user; $$
create definer=`root`#`localhost` trigger `before_create_user`
before insert on `users`
for each row begin
declare fk_parent_user_id int default 0;
select auto_increment into fk_parent_user_id
from information_schema.tables
where table_name = 'users'
and table_schema = database();
insert into user_records ( action, userid, timestamp )
values ( 'created', fk_parent_user_id, now() );
end;
$$
delimiter ;
Observations:
As per mysql documentation on last_insert_id(),
"if you insert multiple rows using a single INSERT statement,
LAST_INSERT_ID() returns the value generated for the first inserted
row only."
hence, depending on last_insert_id() and auto_increment field values in batch inserts seems not reliable.
Change the trigger to after insert instead of before insert and use NEW to get the last inserted id
USE `gknet`;
DELIMITER $$
CREATE DEFINER=`root`#`localhost`
TRIGGER `after_create_user` AFTER INSERT ON `users`
FOR EACH ROW
BEGIN
INSERT INTO user_records (action, userid, timestamp)
VALUES ('CREATED', NEW.ID, NOW() );
END; $$
PLEASE USE AFTER INSERT AND UPDATE
Do not make auto_increment any column you want to manipulate explicitly. That can confuse an engine and cause serious problems. If no column you have used for primary key are auto_increment you can do anything you want with them via triggers. Sure generated values will be rejected if they violate the mandatory uniqness of the primary key.
maybe this solution can
BEGIN
DECLARE id int;
SELECT MAX(table_id)
FROM table
INTO id;
IF id IS NULL THEN
SET NEW.column=(CONCAT('KTG',1));
ELSE
SET NEW.column=(CONCAT('KTG',id+1));
END IF;
END

mysql TRIGGER update field after update

i have 2 table today_plan and kiln_master.
after pattern and itemno inserted to today_plan then need to select matching yeild from kiln_master table and update this value to yeild field in today_plan.
i have created a trigger
CREATE TRIGGER update_yeild AFTER INSERT ON today_plan
FOR EACH ROW UPDATE today_plan
SET yeild= (SELECT kiln_master.yeild from kiln_master,today_plan WHERE today_plan.itemno = kiln_master.item AND today_plan.pattern = kiln_master.pattern ) WHERE itemno=new.itemno AND pattern=new.pattern
what part is wrong with my code
today_plan
DROP TABLE IF EXISTS decsys.today_plan;
CREATE TABLE `today_plan` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`belt` varchar(25) NOT NULL,
`distant` varchar(25) NOT NULL,
`pjtno` varchar(15) DEFAULT NULL,
`pattern` varchar(25) NOT NULL,
`itemno` varchar(25) NOT NULL,
`pro_qty` varchar(25) NOT NULL,
`act_qty` varchar(25) NOT NULL,
`yeild` varchar(25) NOT NULL,
`remark` varchar(100) NOT NULL,
`shipment` varchar(15) NOT NULL,
`temp` varchar(15) NOT NULL,
`fire_date` date NOT NULL,
`kiln` varchar(10) DEFAULT NULL,
`kiln_plan` varchar(15) NOT NULL,
`kiln_act` varchar(15) NOT NULL,
`ins_date` date NOT NULL,
`ins_act` varchar(15) NOT NULL,
`plandate` date NOT NULL,
`ship_date` date NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=31 DEFAULT CHARSET=utf8;
kiln_master
DROP TABLE IF EXISTS decsys.kiln_master;
CREATE TABLE `kiln_master` (
`kid` int(7) NOT NULL,
`pattern` varchar(30) NOT NULL,
`item` varchar(30) NOT NULL,
`yeild` double NOT NULL,
`temp` int(6) NOT NULL,
`kiln` varchar(10) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
error
#1442 - Can't update table 'today_plan' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
thank you very much
You're trying to update the row after it has been inserted, isn't it better to do before so that it gets inserted with the correct values? That'd be something like;
CREATE TRIGGER update_yeild BEFORE INSERT ON today_plan
FOR EACH ROW
SET NEW.yeild = COALESCE((SELECT kiln_master.yeild
FROM kiln_master
WHERE NEW.itemno = kiln_master.item
AND NEW.pattern = kiln_master.pattern
LIMIT 1), 0);