数据库主键自增表中自增型字段的值一定连续吗?

  描述1:学号总共 12 位,由字母 XH+年+6 位数字编号组成(如 XH), 必须唯一, 在新增时自动生成,数字编号自动增长  问题:数据库中自增的都是int型,变成字符串该怎么办呢?因为在数据库端实现自增,不能在软件端处理了。在不考虑  几个函数的解释:  Right(str,len)-字段返回最右边的len个字符的字符串str  MAX()-字段中最大的值  IsNull() 如为空就为空  思路:  首先这是个自定义函数  前面的XH固定  年为YEAR(GETDATE())  查找表中该列中的最大值取到后(右)6位,最大的+1create function f_GetStudentGuid()returns varchar(12)asbegindeclare @studentGuid varchar(12)select @studentGuid='XH'+CONVERT(varchar,YEAR(GETDATE()))+RIGHT(1000000+ISNULL(RIGHT(MAX(studentGuid),6),0)+1,6)from StudentInforeturn @studentGuidend  ---------------------  --为表添加 默认值  ALTER TABLE studentinfo ADD DEFAULT ([dbo].[f_GetStudentGuid]()) FOR StudentGuid  GO  --也可以在图形化界面输入[dbo].[f_GetStudentGuid]()  下面通过输入数据获取以下信息,其中有现实中的数据,为了保护,马赛克了。  图1  好了,现在我仿照上面的做法来完成以下几个案例。  案例1:成绩 Guid 总共 15 位,由字母 CJ+年月日 +数字编号 组成(如CJ1),必须唯一,在新增时自动生成,数字编号自动增长。  那么,下面我就来写这个函数  -----------------------------  ------------------------------create function f_GetScoreGuid()returns varchar(15)asbegindeclare @ScoreGuid varchar(15)declare @time varchar(8)set @time=CONVERT(varchar,YEAR(GETDATE()))+RIGHT('00'+CONVERT(varchar,month(getdate())),2)+CONVERT(varchar,DAY(GETDATE()))select @ScoreGuid='CJ'+@time+RIGHT(100000+ISNULL(RIGHT(MAX(ScoreGuid),5),0)+1,5)from ScoreInforeturn @ScoreGuidend  说明:获取时间,注意剩余的位数  注意:月份的获取  RIGHT('00'+CONVERT(varchar,month(getdate())),2)    图2  为了巩固练习,我们继续来完成几个案例  案例2:员工编号总共 6 位,由字母 YG+4 位数字编号组成(如 YG0001),必须唯一,在新增时自动生成,数字编号自动增长。  这个案例只要把时间去掉,减少编号的位数即可。  你也来做一个练习吧!  案例3:工资记录 ID 总共 12 位,由字母 GZ+年月+4 位数字编号组成(如 GZ),  必须唯一,在新增时自动生成,数字编号自动增长。  总结:  1 函数的写法。  2 表 字段对应好  3 如何设置默认值  4 以后可能会接触更加复杂的流水号,这里的方法可能就不适合了。就当一个简单的思维练习吧。[DB][MySql]关于取得自增字段的值、及@@IDENTITY与并发性问题
对于刚从Oracle转向MySql的人都会为,MySql中没有Oracle里的Sequence而感到困惑。MySql中没有了Sequence,那么MySql的主键用什么方式来实现最好呢?
主要有以下几种方式:
1、自增字段作为主键。【推荐方案】
MySql虽然比Oracle少了Sequence,但是多了字段的自增长特性。
插入完了以后可以通过执行【SELECT @@IDENTITY】获取上一条插入语句中生成的自增长字段的值。
这个语句很特别,没有关联到特定的SQL语句,会 让人感觉迷糊,他到底是怎么获取值的。在并发情况下会不会获取其他线程执行后的值。
答案是有可能的,但是不用怕、是可控的。只有不当的编码才会导致取到其他线程的值。先来说一下原理:
The Jet OLE DB version 4.0 provider supports the SELECT @@Identity query that allows you to retrieve the value of the auto-increment field generated on your connection. Auto-increment values used on other connections to your database do not affect the results of this specialized query. This feature works with Jet 4.0 databases but not with older formats.
大致意思是【SELECT @@IDENTITY】获取的是当前数据库连接的前一次执行的值。其他连接执行的值不会影响当前线程。时下流行的框架(如Spring-jdbc、mybatis、hibernate)的数据库连接都是存在ThreadLocal中的、是线程隔离的,所以不会获取到其他线程中的【SELECT @@IDENTITY】值。当多线程时、强制把连接传给各个线程同时执行时才会取到其他线程的【SELECT @@IDENTITY】。
2、在MySql中模拟Sequence
第一步:创建--Sequence 管理表
DROP TABLE IF EXISTS
CREATE TABLE WFO_SEQ(
name VARCHAR(50) NOT NULL,
current_value INT NOT NULL,
increment INT NOT NULL DEFAULT 1,
PRIMARY KEY (name)
) ENGINE=InnoDB;
第二步:创建--取当前值的函数
DROP FUNCTION IF EXISTS
DELIMITER $
CREATE FUNCTION currval (seq_name VARCHAR(50))
RETURNS INTEGER
LANGUAGE SQL
DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
DECLARE value INTEGER;
SET value = 0;
SELECT current_value INTO value
FROM WFO_SEQ
WHERE name = seq_
DELIMITER ;
第三步:创建--取下一个值的函数
DROP FUNCTION IF EXISTS
DELIMITER $
CREATE FUNCTION nextval (seq_name VARCHAR(50))
RETURNS INTEGER
LANGUAGE SQL
DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
DECLARE C_V INTEGER;
UPDATE WFO_SEQ SET CURRENT_VALUE = CURRENT_VALUE + INCREMENT WHERE NAME = SEQ_NAME;
C_V = CURRVAL(SEQ_NAME);
C_V = -1 THEN
INSERT INTO WFO_SEQ(NAME,
CURRENT_VALUE,
INCREMENT)
VALUES(SEQ_NAME, 1, 1);
RETURN C_V;
DELIMITER ;
第四步:创建--更新当前值的函数
DROP FUNCTION IF EXISTS
DELIMITER $
CREATE FUNCTION setval (seq_name VARCHAR(50), value INTEGER)
RETURNS INTEGER
LANGUAGE SQL
DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
UPDATE WFO_SEQ
SET current_value = value
WHERE name = seq_
RETURN currval(seq_name);
DELIMITER ;
第五步:测试函数功能
SELECT SETVAL('TestSeq',
10);---设置指定sequence的初始值
SELECT CURRVAL('TestSeq');--查询指定sequence的当前值
SELECT NEXTVAL('TestSeq');--查询指定sequence的下一个值
(window.slotbydup=window.slotbydup || []).push({
id: '2467140',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467141',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467143',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467148',
container: s,
size: '1000,90',
display: 'inlay-fix' > 
SQL Server自增字段插入值的步骤
    时间:
19:28    阅读:
    整理: 红客VIP
  我们今天主要与大家一起分享的是SQL 数据库之向SQL 中值的正确操作以及对其实际操作中要用到的实际操作代码的描述以下就是文章的详细内容的具体描述
  通常情况下不能向 SQL Server 值如果非要这么干的话SQL Server 就会好不客气地给你个错误警告
  Server:&Msg&&Level&&State&&Line& &  Cannot&insert&explicit&value&for&identity&column&in&table&t&when&identity_insert&is&set&to&OFF&
  这个错误消息提示我们如果向 SQL Server 自增字段插入值需要设置 identity_insert 选项为 on
  set&identity_insert&on&
  看具体的一个例子
  create&table&dbot &  ( &  id&int&identity()&not&null &  name&varchar() &  ) &  set&identity_insert&t&on &  insert&into&t&(id&name)&values(&sqlstudy) &  set&identity_insert&t&off &
  注意的是自增字段插入值后要及时把 identity_insert 设置为 off,
【】【】【】【】【】33653人阅读
有一个表StuInfo,里面只有两列 StuID,StuName其中StuID是int型,主键,自增列。现在我要插入数据,让他自动的向上增长,insert into StuInfo(StuID,StuName) values(????) 如何写?
INSERT INTO StuInfo(StuID,StuName) VALUES (NULL, `字符`)或者
INSERT INTO StuInfo(StuName) VALUES (`字符`)
INSERT和REPLACE语句的功能都是向表中插入新的数据。这两条语句的语法类似。它们的主要区别是如何处理重复的数据。
1. INSERT的一般用法
中的INSERT语句和标准的INSERT不太一样,在标准的SQL语句中,一次插入一条记录的INSERT语句只有一种形式。
INSERT INTO tablename(列名…) VALUES(列值);
而在MySQL中还有另外一种形式。
INSERT INTO tablename SET column_name1 = value1, column_name2 = value2,…;
第一种将列名和列值分开了,在使用时,列名必须和列值的数一致。如下面的语句向users表中插入了一条记录:
INSERT INTO users(id, name, age) VALUES(123, '姚明', 25);
第二种方法允许列名和列值成对出现和使用,如下面的语句将产生中样的效果。
INSERT INTO users SET id = 123, name = '姚明', age = 25;
如果使用了SET方式,必须至少为一列赋值。如果某一个字段使用了省缺值(如默认或自增值),这两种方法都可以省略这些字段。如id字段上使用了自增值,上面两条语句可以写成如下形式:
INSERT INTO users (name, age) VALUES('姚明',25);
INSERT INTO uses SET name = '姚明', age = 25;
MySQL在VALUES上也做了些变化。如果VALUES中什么都不写,那MySQL将使用表中每一列的默认值来插入新记录。
INSERT INTO users () VALUES();
如果表名后什么都不写,就表示向表中所有的字段赋值。使用这种方式,不仅在VALUES中的值要和列数一致,而且顺序不能颠倒。 INSERT INTO users VALUES(123, '姚明', 25);
如果将INSERT语句写成如下形式MySQL将会报错。
INSERT INTO users VALUES('姚明',25);
2. 使用INSERT插入多条记录
看到这个标题也许大家会问,这有什么好说的,调用多次INSERT语句不就可以插入多条记录 了吗!但使用这种方法要增加服务器的负荷,因为,执行每一次SQL服务器都要同样对SQL进行分析、优化等操作。幸好MySQL提供了另一种解决方案,就 是使用一条INSERT语句来插入多条记录。这并不是标准的SQL语法,因此只能在MySQL中使用。
INSERT INTO users(name, age)
VALUES('姚明', 25), ('比尔.盖茨', 50), ('火星人', 600);
上面的INSERT 语句向users表中连续插入了3条记录。值得注意的是,上面的INSERT语句中的VALUES后必须每一条记录的值放到一对(…)中,中间使用&,&分割。假设有一个表table1
CREATE TABLE table1(n INT);
如果要向table1中插入5条记录,下面写法是错误的:
INSERT INTO table1 (i) VALUES(1,2,3,4,5);
MySQL将会抛出下面的错误
ERROR 1136: Column count doesn't match value count at row 1
而正确的写法应该是这样:
INSERT INTO t able1(i) VALUES(1),(2),(3),(4),(5);
当然,这种写法也可以省略列名,这样每一对括号里的值的数目必须一致,而且这个数目必须和列数一致。如:
INSERT INTO t able1 VALUES(1),(2),(3),(4),(5);
3. REPLACE语句
我们在使用时
可能会经常遇到这种情况。如果一个表在一个字段上建立了唯一索引,当我们再向这个表中使用已经存在的键值插入一条记录,那将会抛出一个主键冲突的错误。当 然,我们可能想用新记录的值来覆盖原来的记录值。如果使用传统的做法,必须先使用DELETE语句删除原先的记录,然后再使用INSERT插入新的记录。 而在MySQL中为我们提供了一种新的解决方案,这就是REPLACE语句。使用REPLACE插入一条记录时,如果不重复,REPLACE就和 INSERT的功能一样,如果有重复记录,REPLACE就使用新记录的值来替换原来的记录值。
使用REPLACE的最大好处就是可以将DELETE和INSERT合二为一,形成一个原子操作。这样就可以不必考虑在同时使用DELETE和INSERT时添加事务等复杂操作了。
在使用REPLACE时,表中必须有唯一索引,而且这个索引所在的字段不能允许空值,否则REPLACE就和INSERT完全一样的。
在执行REPLACE后,系统返回了所影响的行数,如果返回1,说明在表中并没有重复的记 录,如果返回2,说明有一条重复记录,系统自动先调用了DELETE删除这条记录,然后再记录用INSERT来插入这条记录。如果返回的值大于2,那说明 有多个唯一索引,有多条记录被删除和插入。
REPLACE的语法和INSERT非常的相似,如下面的REPLACE语句是插入或更新一条记录。
REPLACE INTO users (id,name,age) VALUES(123, '赵本山', 50);
插入多条记录:
REPLACE INTO users(id, name, age)
VALUES(123, '赵本山', 50), (134,'Mary',15);
REPLACE也可以使用SET语句
REPLACE INTO users SET id = 123, name = '赵本山', age = 50;
上面曾提到REPLACE可能影响3条以上的记录,这是因为在表中有超过一个的唯一索引。在 这种情况下,REPLACE将考虑每一个唯一索引,并对每一个索引对应的重复记录都删除,然后插入这条新记录。假设有一个table1表,有3个字段a, b, c。它们都有一个唯一索引。
CREATE TABLE table1(a INT NOT NULL UNIQUE,b INT NOT NULL UNIQUE,c INT NOT NULL UNIQUE);
假设table1中已经有了3条记录
下面我们使用REPLACE语句向table1中插入一条记录。
REPLACE INTO table1(a, b, c) VALUES(1,2,3);
返回的结果如下
Query OK, 4 rows affected (0.00 sec)
在table1中的记录如下
我们可以看到,REPLACE将原先的3条记录都删除了,然后将(1, 2, 3)插入。
二、UPDATE
UPDATE的功能是更新表中的数据。这的语法和INSERT的第二种用法相似。必须提供表名以及SET表达式,在后面可以加WHERE以限制更新的记录范围。
UPDATE table_anem SET column_name1 = value1, column_name2 = value2, ...
WHERE ... ;
如下面的语句将users表中id等于123的记录的age改为24
UPDATE users SET age = 24 WHERE id = 123;
同样,可以使用UPDATE更新多个字段的值 UPDATE users SET age = 24, name = 'Mike' WHERE id = 123;
上面的UPDATE语句通过WHERE指定一个条件,否则,UPDATE将更新表中的所有记录的值。
在使用UPDATE更新记录时,如果被更新的字段的类型和所赋的值不匹配时,MySQL将这 个值转换为相应类型的值。如果这个字段是数值类型,而且所赋值超过了这个数据类型的最大范围,那么MySQL就将这个值转换为这个范围最大或最小值。如果 字符串太长,MySQL就将多余的字符串截去。如果设置非空字段为空,那么将这个字段设置为它们的默认值,数字的默认值是0,字符串的默认值是空串(不是 null,是&&)。
有两种情况UPDATE不会对影响表中的数据。
1. 当WHERE中的条件在表中没有记录和它匹配时。
2. 当我们将同样的值赋给某个字段时,如将字段abc赋为'123',而abc的原值就是'123'。
和INSERT、REPLACE一样,UPDATE也返回所更新的记录数。但这些记录数并不包括满足WHERE条件的,但却未被更新的记录。如下同的UPDATE语句就未更新任何记录。
UPDATE users SET age = 30 WHERE id = 12;
Query OK, 0 rows affected (0.00 sec)
需要注意的时,如果一个字段的类型是TIMESTAMP,那么这个字段在其它字段更新时自动更新。
在有些时候我们需要得到UPDATE所选择的行数,而不是被更新的行数。我们可以通过一些API来达到这个目的。如MySQL提供的C API提供了一个选项可以得到你想要的记录数。而MySQL的JDBC驱动得到的默认记录数也是匹配的记录数。
UPDATE和REPLACE基本类似,但是它们之间有两点不同。
1. UPDATE在没有匹配记录时什么都不做,而REPLACE在有重复记录时更新,在没有重复记录时插入。
2. UPDATE可以选择性地更新记录的一部分字段。而REPLACE在发现有重复记录时就将这条记录彻底删除,再插入新的记录。也就是说,将所有的字段都更新了。
三、DELETE和TRUNCATE TABLE
在MySQL中有两种方法可以删除数据,一种是DELETE语句,另一种是TRUNCATE TABLE语句。DELETE语句可以通过WHERE对要删除的记录进行选择。而使用TRUNCATE TABLE将删除表中的所有记录。因此,DELETE语句更灵活。
如果要清空表中的所有记录,可以使用下面的两种方法:
DELETE FROM table1
TRUNCATE TABLE table1
其中第二条记录中的TABLE是可选的。
如果要删除表中的部分记录,只能使用DELETE语句。
DELETE FROM table1 WHERE ...;
如果DELETE不加WHERE子句,那么它和TRUNCATE TABLE是一样的,但它们有一点不同,那就是DELETE可以返回被删除的记录数,而TRUNCATE TABLE返回的是0。
如果一个表中有自增字段,使用TRUNCATE TABLE和没有WHERE子句的DELETE删除所有记录后,这个自增字段将起始值恢复成1.如果你不想这样做的话,可以在DELETE语句中加上永真的WHERE,如WHERE 1或WHERE true。
DELETE FROM table1 WHERE 1;
上面的语句在执行时将扫描每一条记录。但它并不比较,因为这个WHERE条件永远为true。这样做虽然可以保持自增的最大值,但由于它是扫描了所有的记录,因此,它的执行成本要比没有WHERE子句的DELETE大得多。
DELETE和TRUNCATE TABLE的最大区别是DELETE可以通过WHERE语句选择要删除的记录。但执行得速度不快。而且还可以返回被删除的记录数。而TRUNCATE TABLE无法删除指定的记录,而且不能返回被删除的记录。但它执行得非常快。
和标准的SQL语句不同,DELETE支持ORDER BY和LIMIT子句,通过这两个子句,我们可以更好地控制要删除的记录。如当我们只想删除WHERE子句过滤出来的记录的一部分,可以使用LIMIB, 如果要删除后几条记录,可以通过ORDER BY和LIMIT配合使用。假设我们要删除users表中name等于&Mike&的前6条记录。可以使用如下的DELETE语句:
DELETE FROM users WHERE name = 'Mike' LIMIT 6;
一般MySQL并不确定删除的这6条记录是哪6条,为了更保险,我们可以使用ORDER BY对记录进行排序。
DELETE FROM users WHERE name = 'Mike' ORDER BY id DESC LIMIT 6;
将B表查询的数据插入A表:
insert into A select 。。。from B where。。。
insert into A (。。。)select 。。。from B where。。。
将B表的值更新到A表:
update A set a = (select b from B where B.id = A.id) where exists(select 1 from B where id = A.id) and 。。。
同时删除多表数据:
delete A,B from A,B where A.id = B.id and 。。。
delete from A,B using A,B where A.id = B.id and 。。。
1.建表时就创建自增列:
create table test
&id int auto_increment primary key,
&name varchar(20) not null,
&password varchar(20) not null
insert into test values(null,'aa','aa');
insert into test values(null,'bb','bb');
&&&&& 插入语句时,自增列的值为NULL。
2、创建表格后添加: alter table table1 add id int auto_increment primary key自增字段,一定要设置为primary key.&
注:只有int类型且为primary key 才可以使用auto_increment.
如果用hibernate作为持久层,那么主键ID处用identity类型.
对于一个表主键的选择,从架构设计角度来说,尽量设计一个与业务无关的字段来作为主键会对系统更好
当然,这势必会增加表数据量的大小,可能有些人会认为这个副作用不值得而选择一个有业务意义的字段(或者多个字段)来作为主键
但是对于大多数时候,这个字段所增加的物理存储空间实际上是很小的,并没有很多人想象的那么可怕。而带来逻辑上的简单是很可观的。
另外,是否选择自增类型作为主键,这个可以说是各有好处,如果用自增,应用可以不care这个主键的值得设定,但是有在高并发下成为瓶颈的风险,当然如果并发并不是非常非常高的话,一般不会成为瓶颈。如果自己控制这个主键值的话,更需要付出一点点代价来生成这个值,并发问题可以通过扩展应用集群来解决。
2种解决办法&
1.修改你的数据库表,将ID设为自增长,注:只有主键才可以设置为自增长&
例:CREATE TABLE `message ` (`id` INT(8) NOT NULL AUTO_INCREMENT, PRIMARY KEY(`id`));&
2.代码中进行处理&
int id = 0;&
..................&
String sql=&select max(id) as id from message&;&
rs = ps.executeQuery(sql);//查询出最大ID&
if(rs.next){//如果有ID,原有ID+1&
id = rs.getInt(&id&)+1;&
}else{//否则 ID 初始为0&
//下面接你写的代码就OK了&
PreparedS&
String sql=&insert message (id,name,msg) value(?,?,?)&&
ps.setString(1,id);&
ps.setString(2,name);&
ps.setString(3,msg);
博客分类:
mysql数据库使用auto_increment 字段来辅助为自增列赋值。
SHOW VARIABLES LIKE 'auto_incre%';
auto_increment_increment 1
auto_increment_offset 1
auto_increment_increment&&= 1 ,每次插入数据,id++;auto_increment_offset =1 ,说明从1开始。
一般情况下auto_increment_increment=1,auto_increment_offset=1.是默认初始值。
我们可以在my.cnf文件中进行重新指定。auto_increment满足一个数学当纳法推导公
value=auto_increment_increment*N+auto_increment_offset
表中有auto_increment列,innodb用一种锁策略来保正这个auto_increment列值。
如果我们创建一个表,指定了auto_increment表。那么innodb会维护一个auto_increment
当访问这个计数器,innodb会使用表级锁来锁定这访问过程,这个发生在分析auto_increment
值的过程中,而不是在一个执行事务中。也就是说:这个访问发生在事务执行前面。所以和这个锁
不是发生整个事务过程中,仅仅是分析语句判断出auto_increment这一过程中.
auto_increment计数器,一直维护在内存中,当server重启或是停止后重启,innodb会为每个表
初始化这个计数器.
对一个含有自增列(通常为id)的表执行
SHOW CREATE TABLE table_
&可以得到类似输出:
CREATE TABLE `news` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`title` varchar(255) NOT NULL,
`url` varchar(255) NOT NULL,
`pub_date` datetime NOT NULL,
`site` tinyint(4) NOT NULL,
`created_at` datetime NOT NULL,
`updated_at` datetime DEFAULT NULL,
`org` varchar(255) DEFAULT NULL,
`author` varchar(255) DEFAULT NULL,
`trend` tinyint(4) DEFAULT '-1',
`md5url` char(32) NOT NULL,
`content` longtext NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `md5url` (`md5url`),
KEY `pub_date` (`pub_date`),
KEY `created_at` (`created_at`),
KEY `title` (`title`)
) ENGINE=InnoDB AUTO_INCREMENT=704677 DEFAULT CHARSET=utf8
其中该状态下,表中AUTO_INCREMENT 字段值为704677 ,说明下一个插入的id 为704677 ,同时插入成功后,AUTO_INCREMENT=704678.
mysql 数据库中的id设为自增,容易产生id不连续的问题。有时将一个表中的所有数据清除,但是在插入数据时,id还是在未清除前的基础上累加。
要解决的问题:
1. 删除数据,同时要求再次插入数据时,id从1 开始累计
(1) TRUNCATE TABLE table_
(2)&DELETE FROM&table_ & &
&ALTER TABLEtable_name&auto_increment =1 ;
对上面两种方法进行一下分析。Truncate table 表名 速度快,而且效率高,因为:TRUNCATE TABLE 在功能上与不带 WHERE 子句的 DELETE 语句相同:二者均删除表中的全部行。但 TRUNCATE TABLE 比 DELETE 速度快,且使用的系统和事务日志资源少。DELETE 语句每次删除一行,并在事务日志中为所删除的每行记录一项。TRUNCATE
TABLE 通过释放存储表数据所用的数据页来删除数据,并且只在事务日志中记录页的释放。
  TRUNCATE TABLE 删除表中的所有行,但表结构及其列、约束、索引等保持不变。新行标识所用的计数值重置为该列的种子。如果想保留标识计数值,请改用 DELETE。如果要删除表定义及其数据,请使用
DROP TABLE 语句。
2. 查看当前状态下一个表的auto_increment值:
SHOW TABLE STATUS LIKE 'table_name'
Engine: InnoDB
Version: 10
Row_format: Compact
Rows: 2449
Avg_row_length: 93
Data_length: 229376
Max_data_length: 0
Index_length: 114688
Data_free: 0
Auto_increment: 2353
Create_time:
Update_time: NULL
Check_time: NULL
Collation: utf8_general_ci
Checksum: NULL
Create_options:
&&可以查看该表当前的Auto_increment的值。
3. 对有些失败插入操作,如果不是语法错误,比如重复的唯一键值,也会造成自增id的不连续。
4.&5.1.22之前,innodb使用一个表锁解决自增字段的一致性问题(内部是用一个计数器维护,每次自增时要加表锁),如果一行一行的插入数据则没有什么问题,但是如果大量的并发插入就废了,表锁会引起SQL堵塞,不但影响效率,而且可能会瞬间达到max_connections而崩溃。在
5.1.22之后,innodb使用新的方式解决自增字段一致性问题,对于可以预判行数的insert语句,innodb使用一个轻量级的互斥量。如:某一insert语句1执行前,表的AUTO_INCREMENT=1,语句1的插入行数已知为3,innodb在语句1的实际插入操作执行前就预分配给该语句三个自增值,当有一个新的insert语句2要执行时,读取的AUTO_INCREMENT=4,这样虽然语句1可能还没有执行完,语句2就可直接执行无需等待语句2。这种方式对于可预判插入行数的插入语句有效,如:insert和replace。对于无法提前获知插入行数的语句,如:insert...select...、replace...select...和load
data则innodb还是使用表锁。
insert语句中有时会显示的设置自增字段的值,对于这种情况innodb还是会预分配给语句总行数的自增值而不是只有实际使用系统自增的行。因而有可能会造成自增字段的值不连续。如:
INSERT INTO t1 (c1,c2) VALUES (1,'a'), (NULL,'b'), (5,'c'), (NULL,'d');
&c1 为自增字段,实际的AUTO_INCREMENT 会大2。
设置新自增互斥方式:通过配置选项:innodb_autoinc_lock_mode,它是专门用来在使用auto_increment的情况下调整锁策略的,目前有三种选择:
innodb_autoinc_lock_mode = 0 (“traditional” lock mode:全部使用表锁)
innodb_autoinc_lock_mode = 1 (默认)(“consecutive” lock
mode:可预判行数时使用新方式,不可时使用表锁)&
innodb_autoinc_lock_mode = 2 (“interleaved” lock
mode:全部使用新方式,不安全,不适合replication)
字增序列的基本知识:
自增字段的数据类型必须为:,,,,中的一种,并且必须作为主键或联合主键的一部分。若是作为主键的一部分,自增序列字段值将会丧失唯一性保证。
自增序列,对语句敏感,读,语句是不敏感的。演示示例:
DEFAULT CHARSET=utf8;
DEFAULT CHARSET=utf8
DEFAULT CHARSET=utf8 |
update auto_test set ID=ID+20 WHERE ID =10;
CHARSET=utf8 |
所以若真的特殊情况下,需要使用语句更新值,而且更新后的自增序列的最大值超过定义中的值,就必须使用类似字句:
还提供了两个全局参数与,用于配置实例的自增序列增长起始值与步长。
,则设置自增序列增长的步长为;
,则设置自增序列的起始位置为;
若使用这个特性与复制功能结合的话,就可以方便地实现的两边读写,以及更多的应用扩展。
&残留问题:
自增ID如何实现该条记录被重复采集时内容不重复??
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:570840次
积分:6240
积分:6240
排名:第2323名
原创:61篇
转载:408篇
评论:59条
(1)(3)(4)(6)(4)(1)(1)(4)(9)(14)(9)(7)(4)(18)(23)(13)(21)(11)(3)(14)(30)(18)(8)(8)(14)(12)(17)(16)(29)(28)(34)(16)(3)(8)(19)(18)(3)(2)(6)(3)(6)(6)

我要回帖

更多关于 数据库主键自增 的文章

 

随机推荐