Mysql 在存储过程中使用 LAST_INSERT_ID
Posted
技术标签:
【中文标题】Mysql 在存储过程中使用 LAST_INSERT_ID【英文标题】:Mysql use LAST_INSERT_ID in stored procedure 【发布时间】:2012-07-19 15:29:21 【问题描述】:我需要根据插入另一个主表的最后一个 id 创建一个表,为此我创建了以下存储过程:
CREATE PROCEDURE `sp_create_campaign`
(
IN p_vName VARCHAR(70),
IN p_iIdOper INT(11),
IN p_iIdCount INT(11),
IN p_iIdMoney INT(11),
IN p_cPrefix CHAR(2),
IN p_tComment TINYTEXT,
IN p_iIdUser VARCHAR(32),
OUT p_return_code TINYINT UNSIGNED
)
BEGIN
DECLARE p_campaign INT(11);
DECLARE exit handler for sqlexception
BEGIN
-- ERROR
set p_return_code = 1;
rollback;
END;
DECLARE exit handler for sqlwarning
BEGIN
-- WARNING
set p_return_code = 2;
rollback;
END;
START TRANSACTION;
-- Campaign
INSERT INTO `db_campaign`
(`vName`, `iIdOper`, `iIdCount`, `iIdMoney`, `cPrefix`, `tComment`, `iIdUser`, `dRegister`)
VALUES
(p_vName, p_iIdOper, p_iIdCount, p_iIdMoney, p_cPrefix, p_tComment, p_iIdUser, NOW());
SET p_campaign := LAST_INSERT_ID();
-- Sales
SET @s = CONCAT('DROP TABLE IF EXISTS ', 'db_sale_', p_campaign);
PREPARE stm FROM @s;
EXECUTE stm;
SET @x = CONCAT(
'CREATE TABLE ',
'db_sale_', p_campaign,
"(
`iIdSale` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`dDate` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
`dSubtotal` DECIMAL(7,2) UNSIGNED NOT NULL DEFAULT '00.00',
`dTax` DECIMAL(7,2) UNSIGNED NOT NULL DEFAULT '00.00',
`dTotal` DECIMAL(7,2) UNSIGNED NOT NULL DEFAULT '00.00',
`iIdMoney` INT(11) UNSIGNED NOT NULL,
`iIdOper` INT(11) UNSIGNED NOT NULL,
`iIdBankCount` INT(11) UNSIGNED NOT NULL,
`iIdGroup` INT(11) UNSIGNED NOT NULL,
`iIdUser` INT(11) UNSIGNED NOT NULL,
`iIdUserReg` VARCHAR(32) NOT NULL,
`dRegister` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`iIdSale`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;");
PREPARE stm FROM @x;
EXECUTE stm;
COMMIT;
-- SUCCESS
set p_return_code = 0;
END
但问题是只插入第一条记录,建表失败。我哪里失败了?
【问题讨论】:
它有没有抛出任何错误?select p_return_code;
的输出是什么?或评论sqlexception handler
块,看看会发生什么。
我评论了 SQLException 并在末尾添加了:“SELECT p_return_code”。但是我什么都不退!仅:“时间:0.000ms 程序成功执行受影响的行:0”
【参考方案1】:
替换此行:SET p_campaign := LAST_INSERT_ID();
有了这个:SELECT LAST_INSERT_ID() INTO p_campaign ;
【讨论】:
【参考方案2】:如果您使用SET
,则需要=
而不是:=
【讨论】:
【参考方案3】:两件事:
执行DROP
将隐含COMMIT
您的交易。
尝试添加
DEALLOCATE PREPARE stm;
在每个EXECUTE
语句之后。
【讨论】:
我得到了同样的结果。主要问题是获取最后一个 ID。我正在使用相同的存储过程将其他记录直接插入到最新的 ID 中,但仍然无法正常工作。会用于交易吗? 如果 db_campaign 是 MyISAM,您可以删除START TRANSACTION;
、COMMIT;
和 ROLLBACK;
s,因为它们实际上是 NOOP。您可以添加一些日志记录,例如 INSERT INTO syslog SET script='myscript', line='lineno', message=CONCAT('last_insert_id()=', LAST_INSERT_ID());
是的,你是对的。调查 MyISAM 数据库不支持事务。【参考方案4】:
根据last_insert_id()的mysql文档
如果存储过程执行更改 LAST_INSERT_ID() 值的语句,则更改后的值会被过程调用之后的语句看到。
使用类似的东西:
SELECT id INTO p_campaign FROM db_campaign ORDER BY id DESC LIMIT 1;
或者:
SELECT max(id) INTO p_campaign FROM db_campaign;
【讨论】:
以上是关于Mysql 在存储过程中使用 LAST_INSERT_ID的主要内容,如果未能解决你的问题,请参考以下文章