sqlserver如何在插⼊语句给某个字段插⼊id主键_给你代码:
如何压制MySQL主键值。。。
主键增长不连续引起的问题根源⼤都是使⽤了ON DUPLICATE KEY UPDATE 语法。这个语法的好处是可以将“插⼊重复后触发更新”作
为⼀个独⽴可靠的事务来处理,但由此引发的副作⽤是造成主键值的资源浪费,在更新操作频繁的表中,很容易达到主键字段类型允许的最⼤值,造成整表不可⽤。本⽂的⽬的:将不允许重复的数据录⼊到数据库,并保持主键id连续增长。我们通过⼀个基本应⽤案例来⼀步步揭
⽰其⼯作表现,然后给出解决⽅案。
准备⼯作
我们创建⼀个⽤户表,只包含了⼀个⾃增字段id和登录名name,当然真实项⽬中还有密码,性别,昵称等其他字段,为了简单明了起见,
就不让它们掺和进来了。登录名是不允许重复的,所以在字段name上加了唯⼀索引限制:
MariaDB > use kunquerDatabase changedMariaDB [kunquer]> CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID', `nam
现在我们插⼊⼀条记录,并⽴即通过last_insert_id()获取插⼊记录的id:
MariaDB [kunquer]> insert into user(name) values ('******');Query OK, 1 row affected (0.03 sec)MariaDB [kunquer]> insert into user(name) values ('kunque
为了更清晰发现问题,在每次执⾏插⼊更新操作后,使⽤下⾯的sql查询当前user表的⾃增计数器计数,因为它保存的值就是下⼀个执⾏插
insert语句字段顺序⼊操作记录的主键值:
select auto_increment from information_schema.tables where table_schema = 'kunquer' and table_name = 'user'
⾃增计数器现在为4,现在我们故意插⼊⼀条重复的记录,并看看⾃增计数器内容如何变化:
MariaDB [kunquer]> insert into user(name) values ('kunquer');ERROR 1062 (23000): Duplicate entry 'kunquer' for key 'name'MariaDB [kunquer]> select au
虽然上⾯操作失败了,但是计数器仍然+1,这就触发了主键增长不连续的问题,我们先解决Duplicate entry这个问题:使⽤ ON DUPLICATE KEY UPDATE 语句:
MariaDB [kunquer]> insert into user(name) values ('kunquer') on duplicate key update name = 'kunquer';Query OK, 0 rows affected (0.04 sec)MariaDB [ku LAST_INSERT_ID()
现在报错问题解决了,但是通过last_insert_id()获取到的值并不是我们想要的(应该是2),官⽅对last_insert_id()的描述是这样的:
Returns the value generated for an AUTO_INCREMENT column by the previous INSERT or UPDATE statement. Use this function after you have performed an INSERT statement into a table that contains an AUTO_INCREMENT field, or have
used INSERT or UPDATE to set a column value with LAST_INSERT_ID(expr).
返回上⼀步执⾏的插⼊或更新语句中⾃增字段产⽣的值。last_insert_id()应⽤场景:1.对含有⾃增字段的表执⾏插⼊或更新操作;2.
在插⼊或更新表的时候使⽤last_insert_id(expr)来设置某个字段值。
上⼀步的操作我们是满⾜第1条应⽤场景的,但是获取的值与期望不符,我们再试试第2种办法:
MariaDB [kunquer]> insert into user(name) values ('kunquer') on duplicate key update name = 'kunquer', id = last_insert_id(id);Query OK, 0 rows affected (0.03 s
在on duplicate key update 后,我们加了这个更新:
id = last_insert_id(id)
这个意思是告诉last_insert_id(id)将当前保存的计数值设置为被更新的记录对应的id字段值,所以之后调⽤last_insert_id()就显⽰被设置的
id值了。
截⾄⽬前,我们只是对⽤户登录信息重复检查、录⼊和返回正确的主键id做了⼀个靠谱的保障,但是在每次做插⼊或更新操作,将会引起⾃
增计数器的增长,造成很多主键值被浪费掉,那么在这⾥呼应⼀下本⽂主题:如何压制MySQL主键值⾮连续增长呢?
更改innodb_autoinc_lock_mode设置
MariaDB [kunquer]> SELECT @@innodb_autoinc_lock_mode;+----------------------------+| @@innodb_autoinc_lock_mode |+----------------------------+| 1 |+------------
因为模式1会导致产⽣的⾃增值不连续,我们需要将其⼯作模式改为0,即保证⾃增值的连续性。到MySQL配置⽂件my.ini,在[mysqld]
部分添加⼀⾏:
innodb_autoinc_lock_mode = 0
重启MySQL后,执⾏如下语句:
MariaDB [kunquer]> select auto_increment from information_schema.tables where table_schema = 'kunquer' and table_name = 'user';+----------------+| auto_incre 你会神奇的发现计数器居然变回了4,这正是想要的结果,因为⽬前表中只有三条记录。我们再尝试触发些错误:
MariaDB [kunquer]> insert into user(name) values ('kunquer');ERROR 1062 (23000): Duplicate entry 'kunquer' for key 'name'MariaDB [kunquer]> select auto_incr
说明如果插⼊失败或插⼊重复触发更新操作并没有影响表的⾏数时,计数器是不会对这些操作再+1的。为保证该机制对后续正常插⼊⽆影
响,我们再试试插⼊⼀条不重复的数据,看看计数器是否会+1:
MariaDB [kunquer]> insert into user(name) values ('@@@@@@');Query OK, 1 row affected (0.05 sec)MariaDB [kunquer]> select auto_increment from informatio
正常⼯作!需要声明的是:更改服务器设置虽然⽐较省⼼,但改为0后,每次执⾏插⼊或更新操作时,MySQL将会对操作表进⾏整表锁
定,在⾼并发的情况下⾃增锁竞争将会很激烈,拖慢整个系统的响应速度。我们将尝试从编程⾓度寻解决办法。
先更新,更新失败则插⼊
前⾯的逻辑是不管3721,先插⼊,插⼊发现有重复则更新,那反过来是否可⾏呢?先更新,再插⼊?有点反⼈类正常思维对不对?因为⼤
部分情况下,要插⼊的数据肯定是不存在的,更新个锤⼦?!先别急,我们核⼼任务要解决的是主键⾮连续增长的问题,因为需要避免触发duplicate key错误,⽽更新⼀个不存在的记录是不会触发这个错误的。我们通过更新结果就能判断记录存在与否,再决定是否需要执⾏插
⼊操作。
继续我们的⽰例,放在⼀个事务中进⾏包裹,我们先使⽤如下语句更新⼀个不存在的⽤户:
MariaDB [kunquer]> start transaction;Query OK, 0 rows affected (0.00 sec)MariaDB [kunquer]> update user set name = '@@@@@@' where name = '@@
语句成功运⾏,没有报错,只是对数据库⽆任何更改,根据语句影响⾏数可判断登录名是否存在,如果不为0,我们只需提前commit,如
果为0,我们再将登录信息插⼊进来:
MariaDB [kunquer]> insert into user(name) values('@@@@@@');Query OK, 1 row affected (0.06 sec)MariaDB [kunquer]> commit;Query OK, 0 rows affe
这个问题解决核⼼是事务。只有两条更新语句在事务环境中才变得有意义。⼀般在程序编程中,我们会对数据库⼀些通⽤操作进⾏封装,例如:save($table, $data, $duplicate),$table为操作的表名,$data为要插⼊或更新的数据,$duplicate 是⼀个主键重复开关,只有在duplicate为true的时候才开启先更新后插⼊的逻辑,因为考虑到通⽤性,有些表没有主键,也就不会引起本⽂提到的问题。这个⽅法具体
实现⼤家可以在留⾔区贴上来,互相交流⼀下。
当然,我们⼀步⼀步,似魔⿁的步伐,咳……讲了这么多,绕了这么⼤个弯⼦,问题没有变,变的只是思路,只有思路才有更简单的出路。
往期回顾:
给你代码:⽹站登录接⼊
给你代码:⾃建外贸站之PayPal⽀付集成
双语翻译:PayPal PDT 与 IPN 的对⽐

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。