1. MySQL LAST_INSERT_ID() 函数介绍
MySQL LAST_INSERT_ID() 函数返回上一次 INSERT 操作插入的自增主键值。它对于在表中插入新记录和到其他所需表中插入正在引用自动增量值的记录非常有用。使用 LAST_INSERT_ID() 函数前必须保证表中有 AUTO_INCREMENT 字段。
CREATE TABLE users (
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(30) NOT NULL,
password CHAR(32) NOT NULL
);
上述代码为 MySQL 创建了一个名为 users 的表,其中包含自增 id 字段、用户名和密码字段。
1.1. LAST_INSERT_ID() 的使用方法
在使用 MySQL 的 LAST_INSERT_ID() 函数时,必须在 INSERT 操作时进行操作,比如:
INSERT INTO users (username, password)
VALUES ('Alice', MD5('p@ssword')),
('Bob', MD5('SecuRE')),
('John', MD5('123456'));
前面的 INSERT INTO 插入了三行到 users 表中,并将自增 id 设置为 1、2 和 3。要获取上一个插入的自增 id,可以包含 LAST_INSERT_ID() 函数:
SELECT LAST_INSERT_ID();
此命令将显示上一个插入操作的自增 id。
1.2. LAST_INSERT_ID() 的注意事项
请注意,LAST_INSERT_ID() 函数只对当前的 MySQL 连接有效。如果两个连接在同时进行并尝试插入一个表,MySQL 将为每个连接生成不同的自增计数器。
如果同一个连接插入多行,则 LAST_INSERT_ID() 函数只返回插入的第一行的自增 id。
2. 多行插入的影响
在进行多行插入时,LAST_INSERT_ID() 函数仅返回插入的第一行(即 SELECT LAST_INSERT_ID() 命令只返回第一行记录的自增 id)。因此,如果需要访问以前的行自增 id,则必须使用存储过程或 INSERT INTO SELECT 命令。
如果使用有 BYTE_ORDER=0x01234567 行格式的 InnoDB 表,应小心使用增量值。使用该行格式的表的自增属性可能会导致非常大的存储。因为最初的数据存储在扩展区域而不是数据页中。因此,如果可以,请避免使用该行格式。
2.1. 存储过程的使用
让我们先来了解一下存储过程是什么:
存储过程是一些预编译的 SQL 语句的集合。它们可以重复使用并调用。可以在 MySQL 上下文中执行存储过程。存储过程中包含参数,您可以通过参数进行检索。如果需要复杂的操作,存储过程还可以简化代码。
我们可以通过使用存储过程来处理多行插入的自增 id。 以下是使用存储过程的方法:
DELIMITER $$
CREATE PROCEDURE insert_multiple_users()
BEGIN
DECLARE _id INT;
INSERT INTO users (username, password)
VALUES ('Amy', MD5('amy123')),
('Tom', MD5('tom456')),
('Tony', MD5('tony789'));
SET _id = LAST_INSERT_ID();
INSERT INTO user_profile (user_id, age)
VALUES (_id, 25),
(_id + 1, 22),
(_id + 2, 29);
END $$
DELIMITER ;
以上代码中,我们创建了一个存储过程 insert_multiple_users(),其中首先将多行数据插入到 users 表中,并使用 LAST_INSERT_ID() 函数捕获最后插入的自增 id 值 (存储在 _id 变量中)。在插入数据到 user_profile 表时,我们使用了 _id 和 _id + 1 以及 _id + 2 作为 user_id 的值,其值分别来自上面插入数据到 users 表中的三行数据的自增 id 值增加 1。
为了运行存储过程,我们可以运行以下命令:
CALL insert_multiple_users();
存储过程的好处是可以同时在一个事务中执行多个单元。因此,如果在存储过程中出现任何错误,可以将所有数据回滚到前置操作,建立起来和单元测试。
2.2. INSERT INTO SELECT 命令的使用
除了使用存储过程外,还可以使用 INSERT INTO SELECT 命令插入并捕获多行插入的自增 id。以下是使用 INSERT INTO SELECT 命令的方法:
CREATE TABLE temp_user (
id INT UNSIGNED NOT NULL,
username VARCHAR(30) NOT NULL,
password CHAR(32) NOT NULL,
KEY (id)
);
INSERT INTO temp_user (id, username, password)
VALUES (NULL, 'Marry', MD5('123456')),
(NULL, 'Lucy', MD5('p@ssword')),
(NULL, 'Franck', MD5('SecuRE'));
INSERT INTO users (username, password)
SELECT username, password
FROM temp_user;
UPDATE temp_user SET id=LAST_INSERT_ID();
INSERT INTO user_profile (user_id, age)
SELECT id, 25 FROM temp_user WHERE username='Marry'
UNION ALL
SELECT id+1, 22 FROM temp_user WHERE username='Lucy'
UNION ALL
SELECT id+2, 29 FROM temp_user WHERE username='Franck';
DROP TABLE temp_user;
以上代码中,我们首先创建一个名为 temp_user 的临时表,然后使用 INSERT INTO 命令插入多行数据,其中 id 为 NULL,可以根据自增属性进行计算,它们的用户名和密码为 Marry、Lucy 和 Franck。
然后执行 INSERT INTO SELECT 命令,将数据从 temp_user 表插入到 users 表中。接下来更新 temp_user 表中的 id 值,即将 LAST_INSERT_ID() 对应的值分别添加到 temp_user 表中的三个行上。
接着使用 SELECT UNION ALL 命令向 user_profile 表中插入数据。
最后清理临时表:
DROP TABLE temp_user;
3. 总结
在本文中,我们介绍了 MySQL LAST_INSERT_ID() 函数的基础知识和使用方法,以及在多行插入的情况下使用存储过程和 INSERT INTO SELECT 命令捕获自增 id 的方法。对于需要同时插入到多个表中并捕获自增 id 的情况下,存储过程和 INSERT INTO SELECT 命令都是很好的解决方法。
如果需要使用存储过程,请确保您在插入数据之前开启了一个事务,并且如果出现任何错误,则应回滚所有数据。同样,也应该避免使用有 BYTE_ORDER=0x01234567 行格式的 InnoDB 表,以避免引起问题。
总之,了解如何正确地使用 LAST_INSERT_ID() 函数非常重要,这是执行有效的 MySQL 数据库操作的关键。