带有LAST_INSERT_ID()的MySQL函数产生意外结果

用户名

我花了24个小时在此上,需要利用现有的知识来提高速度。

我有这个mysql函数:

DELIMITER $$
USE `db`$$

DROP FUNCTION IF EXISTS `insertindb`$$

CREATE DEFINER=`root`@`localhost` FUNCTION `insertindb`(itemtype  VARCHAR(10), dname VARCHAR (50), id INTEGER, fname VARCHAR(50), lname VARCHAR(50)) RETURNS INT(11)
DETERMINISTIC
BEGIN 
    DECLARE ret INT;
    DECLARE ret2 INT;
    IF itemtype = 'state' THEN 
        INSERT IGNORE INTO state (`name`) VALUES (dname);
        SELECT LAST_INSERT_ID() INTO ret;       
        IF ret = 0 THEN
           SELECT `id` INTO ret2 FROM state WHERE `name` LIKE dname;
           SET ret = ret2;
        END IF;              
    END IF;
  RETURN ret;
END$$

DELIMITER ;

目的?state表中已经存在状态时,它应返回id列(这是自动递增键)。如果不存在,则应将其插入并返回新的(自动)分配的ID。

该功能正在工作,但我不想做两件事:

1)当记录已经存在时,它返回零而不是现有记录的ID。我的代码旨在解决这个问题,但是它不起作用请注意,我在表上定义了一个索引以确保state.name在表中是唯一的,以便INSERT IGNORE可以工作

2)即使记录存在,因此LAST_INSERT_ID()仍保持递增,因此没有插入任何内容。因此,例如,如果状态表仅以一条记录开头(例如id ==> 1,名称==>'State A',),如果我调用该函数2次以尝试重新插入“ State A”(将不会如上面第1点所述插入),然后再次调用它以插入“状态B”,该表现在将具有第二个记录id ==> 4,名称==>“状态B”,跳过id值2和3 。有没有办法让LAST_INSERT_ID有所不同?

现在我的代码

BEGIN 
DECLARE ret,ret2 INT;

IF itemtype = 'state' THEN 
    SELECT `id` INTO ret FROM state WHERE `name` LIKE dname;
    #insert into debug (dump1,dump2) values ('ret will be',ret);
    IF ret IS NULL OR ret = '' THEN

        INSERT IGNORE INTO state (`name`) VALUES (dname);
        SELECT LAST_INSERT_ID() INTO ret2;  
        #SELECT `id` INTO ret FROM state WHERE `name` LIKE dname;
        RETURN ret2;
    ELSE
        RETURN ret;
    END IF; 
END IF;

END $$

蒂姆3880

洛伦兹已经为您提供了解决方案:

 SELECT `id` INTO ret FROM state WHERE `name` LIKE dname;
 IF ret IS NULL THEN
     INSERT IGNORE INTO state (`name`) VALUES (dname);
     SELECT `id` INTO ret FROM state WHERE `name` LIKE dname;
 END IF;         

如果您在同一时间多次调用同一个函数,那么您仍然有可能会在id之间产生间隙,那么您需要使用不同的方法:

1)删除ID上的auto_increment 2)在ID上创建唯一索引3)使用这种查询来插入新值:

INSERT INTO state (name, id)
SELECT dname, MAX(id) + 1 FROM state
WHERE NOT EXISTS (SELECT * FROM state WHERE name=dname);
SELECT id INTO ret FROM state WHERE name=dname;

当MAX(id)返回NULL时,它可能不适用于第一种状态。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章