mysql LAST_INSERT_ID 使用与注意事项
1.在使用MySQL时,若表中含自增字段(auto_increment类型),则向表中insert一条记录后,可以调用last_insert_id()来获得最近insert的那行记录的自增字段值
$mdb->last_insert_id();
但事实上,使用last_insert_id()时有很多注意事项,否则很容易踩到坑。
2.若在同一条insert语句中插入多行(如"insert into tbl_name (col_a, col_b) values ('aa', 'bb'), ('aaa', 'bbb')"这类SQL语句),则last_insert_id()返回的自增字段的"当前值"只在旧值的基础上加1,这与实际情况不符(表中的实际情况是自增字段值在旧值基础上加N)!
3.假设用形如"INSERT ... ON DUPLICATE KEY UPDATE"的SQL语句更新表,此时,若该语句的实际作用是insert操作时,调用last_insert_id()会返回本次insert后自增字段的当前值;而若该语句的实际作用是update操作时,调用last_insert_id()返回的是自增字段的旧值,而非当前更新行的自增字段值,所以这个值无意义(因为调用last_insert_id()是想获取sql影响到的行的自增字段值进而做其它逻辑业务的,如果得到的值并非sql操作影响到的行对应的自增值,则这个值对业务来说无意义),按照MySQL手册的说明,若业务开发者想得到实际update操作影响到的行的自增值,可以用形如"INSERT INTO table (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id), c=3;"的SQL语句来获取。关于带参数的last_insert_id()函数的使用说明,可以参考本文后面的说明。
4.若在SQL中显式指定自增字段的值,如假设某张表由两列(id, name)构成,其中id为自增类型,假设当前表中id值为2,那么,执行"insert into test_tbl (id, name) values (11, 'test3');"后,再执行"select last_insert_id()",可以发现,得到的结果依旧是2。也即,只有自增字段由mysql来分配时,last_insert_id()才可能得到正确的值;SQL中显式更新自增字段值时,last_insert_id()返回的值不可用!
5.如果sql语句执行出错,则调用last_insert_id()的值未定义。例如,若事务因执行出错回滚,则last_insert_id()的值不会恢复到事务执行前的那个值。
6.last_insert_id()的值是由MySQL server来维护的,而且是为每条连接维护独立的值,也即,某条连接调用last_insert_id()获取到的值是这条连接最近一次insert操作执行后的自增值,该值不会被其它连接的sql语句所影响。这个行为保证了不同的连接能正确地获取到它最近一次insert sql执行所插入的行的自增值,也就是说,last_insert_id()的值不需要通过加锁或事务机制来保证其在多连接场景下的正确性。
7.如果通过"insert ignore"语句尝试插入新纪录,假设由于unique key冲突导致插入不成功,则auto_increment计数器不会变化,根据MySQL手册的说明,此时调用last_insert_id()会返回0表示没有新行被插入。但我在MySQL 5.1.73版本上测试的结果显示,last_insert_id()只是维持旧值而已,并不会返回0。
8.last_insert_id(expr)的行为
mysql> CREATE TABLE sequence (id INT NOT NULL); mysql> INSERT INTO sequence VALUES (0);
2) 每条连接执行下面的SQL语句来获取为其自动分配的全局唯一ID
mysql> UPDATE sequence SET id=LAST_INSERT_ID(id+1); mysql> SELECT LAST_INSERT_ID();
相关文章
- 【MySQL】再说MySQL中的 table_id
- 【MySQL】批量删除mysql中数据库中的表
- 【MySql】mysql 数据库数据订正
- mysql中的多行查询结果合并成一个
- MySQL查看数据库性能常用命令
- 关于mysql删除记录后id顺序不连续的解决方法
- Linux下keepalived+mysql 实现高可用
- MySQL数字类型int与tinyint、float与decimal如何选择
- MySQL 使用自增ID主键和UUID 作为主键的优劣比较详细过程(从百万到千万表记录测试)
- MySQL · 答疑解惑 · mysqldump tips 两则
- MySQL-5.6.29源码编译安装记录
- Corosync+Pacemaker+DRBD+Mysql高可用HA配置
- MySQL UNION 和 UNION all 操作符将两个结果集合并一个表
- Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result
- Mysql InnoDB存储引擎的锁相关
- Mysql 如果有多个可选条件怎么加索引_MySQL|mysql-索引
- MySQL使用注意事项(一)
- MYsql 数据库密码忘记(Window)-2(mysql 5.7)
- Mysql与cmd不得不说的秘密
- [转]mysql在已有无分区表增加分区,mysql5.5才有,可以是innodb_file_per_table关闭状态.
- net start mysql 无法启动mysql解决方案之一【NET HELPMSG 3534】
- Android 通过资源Id获取资源名称和通过资源名称获取资源ID
- 〖Python 数据库开发实战 - MySQL篇②〗- 一文通解关系型数据库与非关系型数据库
- [手游新项目历程]-50-Mysql的大字段问题(数据库执行错误: Error=1118, Reason=Row size too large (> 8126))
- 上Mysql com.mysql.jdbc.StatementImpl$CancelTask内存泄漏问题和解决方法
- mysql存储引擎
- MYSQL提权之反弹SHELL——数据库提权属于webshell到管理员的纵向提权,本质还是利用udf提权,无非是在mysql自定义函数中使用了反弹shell而已
- mysql_22 _ MySQL有哪些“饮鸩止渴”提高性能的方法?
- mysql 查看 脏页_MySQL:刷脏页
- Mysql报错:Can't connect to local MySQL server through socket '/tmp/mysql.sock'
- MYSQL UPDATE语句
- MySQL 一文带你详解 mysql binlog
- MySQL中的日期时间类型与格式化方式
- [MySQL] 解决办法: Error: Transaction test error: file /etc/my.cnf from install of mysql-community-server