在系統開發過程中,我們經常要用到唯一編號。使用過mysql的人都應該知道,mysql有一個定義列為自增的屬性:AUTO_INCREMENT。
指定了AUTO_INCREMENT的列必須要建索引,不然會報錯,索引可以為主鍵索引,當然也可以為非主鍵索引。(不一定要做主鍵)
1
2
3
|
mysql>
create
table
t4 (id
int
auto_increment);
ERROR 1075 (42000): Incorrect
table
definition; there can be
only
one auto
column
and
it must be defined
as
a
key
mysql>
|
下面的定義把t5表的主鍵定義為了name,而非自增的id字段
1
2
3
|
mysql>
mysql>
create
table
t5 (id
int
auto_increment,
name
varchar
(20)
primary
key
,
key
(id));
Query OK, 0
rows
affected (0.01 sec)
|
指定了auto_increment的列,在插入時:
-
如果把一個NULL插入到一個AUTO_INCREMENT數據列里去,MySQL將自動生成下一個序列編號。編號從1開始,並1為基數遞增。
-
當插入記錄時,沒有為AUTO_INCREMENT明確指定值,則等同插入NULL值。
12345678910mysql> insert into t5 (id,name) values (
null
,
'test'
);
Query OK,
1
row affected (
0.00
sec)
mysql> select * from t5;
+----+------+
| id | name |
+----+------+
|
2
| test |
+----+------+
1
row
in
set
(
0.00
sec)
-
上面語句等同於下面語句:
1mysql> insert into t5 (name) values (
'test'
);
-
當插入記錄時,如果為AUTO_INCREMENT字段明確指定了一個數值,則會出現兩種情況:
情況一,如果插入的值與已有的編號重復,則會出現出 錯信息,因為AUTO_INCREMENT數據列的值必須是唯一的;
情況二,如果插入的值大於已編號的值,則會把該插入到數據列中,並使在下一個編號將從這個新值開始遞增。
12345678910111213141516171819202122232425262728293031323334## 初始表
mysql> show create table t2\G;
***************************
1
. row ***************************
Table: t2
Create Table: CREATE TABLE `t2` (
`id`
int
(
11
) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8
## 插入數據
mysql> insert into t2 values (
null
),(
null
),(
null
);
Query OK,
3
rows affected (
0.00
sec)
## auto_increment變成
4
mysql> show create table t2\G;
***************************
1
. row ***************************
Table: t2
Create Table: CREATE TABLE `t2` (
`id`
int
(
11
) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=
8
DEFAULT CHARSET=utf8
## 插入
7
mysql> insert into t2 values (
7
);
Query OK,
1
row affected (
0.00
sec)
## auto_increment變成
8
mysql> show create table t2\G;
***************************
1
. row ***************************
Table: t2
Create Table: CREATE TABLE `t2` (
`id`
int
(
11
) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=
8
DEFAULT CHARSET=utf8
換句話說,就是自增字段可以跳過一些編號。
-
對於MyISAM表,如果用UPDATE命令更新自增列,如果列值與已有的值重復,則會出錯。如果大於已有值,則下一個編號從該值開始遞增。但是對於innodb表,update auto_increment字段,會導致發生報錯
MyISAM表的update如下所示
123456789101112131415161718192021222324## 當前狀態
mysql> show create table t2\G;
***************************
1
. row ***************************
Table: t2
Create Table: CREATE TABLE `t2` (
`id`
int
(
11
) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=
8
DEFAULT CHARSET=utf8
1
row
in
set
(
0.00
sec)
## 將id=
7
的數據update為
10
mysql> update t2
set
id=
10
where id=
7
;
Query OK,
1
row affected (
0.00
sec)
Rows matched:
1
Changed:
1
Warnings:
0
## 最新的auto_increment變為
11
mysql> show create table t2\G;
***************************
1
. row ***************************
Table: t2
Create Table: CREATE TABLE `t2` (
`id`
int
(
11
) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=
11
DEFAULT CHARSET=utf8
1
row
in
set
(
0.00
sec)
Innodb表的update操作如下所示
(可以看到在update前后,表定義語句沒有變化),接着執行insert會導致主鍵錯誤!
12345678910111213141516171819202122mysql> show create table t3\G;
***************************
1
. row ***************************
Table: t3
Create Table: CREATE TABLE `t3` (
`id`
int
(
11
) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=
8
DEFAULT CHARSET=utf8
1
row
in
set
(
0.00
sec)
## updae更新操作
mysql> update t3
set
id=
10
where id=
7
;
Query OK,
1
row affected (
0.27
sec)
Rows matched:
1
Changed:
1
Warnings:
0
mysql> show create table t3\G;
***************************
1
. row ***************************
Table: t3
Create Table: CREATE TABLE `t3` (
`id`
int
(
11
) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=
8
DEFAULT CHARSET=utf8
1
row
in
set
(
0.00
sec)
Innodb表繼續插入會導致報錯,但是只會報錯一次,跳過10之后會正常插入
12345678mysql> insert into t3 values (
null
);
Query OK,
1
row affected (
0.46
sec)
mysql> insert into t3 values (
null
);
Query OK,
1
row affected (
0.11
sec)
mysql> insert into t3 values (
null
);
ERROR
1062
(
23000
): Duplicate entry
'10'
for
key
'PRIMARY'
-
被delete語句刪除的id值,除非sql中將id重新插入,否則前面空余的id不會復用。
-
delete from t3該語句不會引起auto_increment的變化,
1234567891011mysql>
delete
from t3;
Query OK,
8
rows affected (
0.34
sec)
mysql> show create table t3\G;
***************************
1
. row ***************************
Table: t3
Create Table: CREATE TABLE `t3` (
`id`
int
(
11
) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=
18
DEFAULT CHARSET=utf8
1
row
in
set
(
0.00
sec)
truncate table t3 該語句會引起auto_increment的變化,從頭開始。
1234567891011mysql> truncate table t3;
Query OK,
0
rows affected (
0.53
sec)
mysql> show create table t3\G;
***************************
1
. row ***************************
Table: t3
Create Table: CREATE TABLE `t3` (
`id`
int
(
11
) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1
row
in
set
(
0.00
sec)
-
last_insert_id()函數可獲得自增列自動生成的最后一個編號。但該函數只與服務器的本次會話過程中生成的值有關。如果在與服務器的本次會話中尚未生成AUTO_INCREMENT值,則該函數返回0。
修改AUTO_INCREMENT字段的起始值
可用alter table table_name AUTO_INCREMENT=n命令來重設自增的起始值。
但是如果設置的n比目前的數值小的話,執行的sql不會報錯,但是不會生效!MyISAM和Innodb均是如此。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
mysql> show create table t2;
+-------+-----------------------
CREATE TABLE `t2` (
`id`
int
(
11
) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=
14
DEFAULT CHARSET=utf8
1
row
in
set
(
0.00
sec)
mysql>
mysql> alter table t2 auto_increment=
2
;
Query OK,
6
rows affected (
0.04
sec)
Records:
6
Duplicates:
0
Warnings:
0
mysql> show create table t2;
+-------+--------------------
CREATE TABLE `t2` (
`id`
int
(
11
) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=
14
DEFAULT CHARSET=utf8
|
auto_increment_increment & auto_increment_offset 兩個變量的介紹
這兩個參數作用:控制自增列AUTO_INCREMENT的行為,用於MASTER-MASTER之間的復制,防止出現重復值。
兩個變量均可以設置為全局或局部變量,並且假定每個值都可以為1到65,535之間的整數值。將其中一個變量設置為0會使該變量為1。如果試圖將這些變量設置為大於65,535或小於0的值,則會將該值設置為65,535。如果向將auto_increment_increment或auto_increment_offset設置為非整數值,則會給出錯誤,並且變量的實際值在這種情況下保持不變。
兩個值的含義:
auto_increment_increment:自增值的自增量
auto_increment_offset: 自增值的偏移量
設置了兩個值之后,改服務器的自增字段值限定為:
auto_increment_offset + auto_increment_increment*N 的值,其中N>=0,但是上限還是要受定義字段的類型限制。
比如:
auto_increment_offset=1
auto_increment_increment=2
那么ID則是所有的奇數[1,3,5,7,.....]
如果:
auto_increment_offset=5
auto_increment_increment=10
那么ID則是所有的奇數[5,15,25,35,.....]
查看當前值:
1
2
3
4
5
6
7
|
mysql> show
var
iables like
'%auto_increment%'
;
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| auto_increment_increment |
1
|
| auto_increment_offset |
1
|
+--------------------------+-------+
|
配置auto-increment-increment&auto-increment-offset的值:
(1):修改配置文件,重啟mysqld
vi my.cnf
將
auto-increment-increment = 2
auto-increment-offset = 2
加入到mysqld相關的配置中
(2):通過set命令修改,不需要重啟mysqld,一般需要用set global來設置
1
2
|
set
global auto_increment_increment=
2
;
set
global auto_increment_offset=
2
;
|
注意:在一個會話中,如果用set global 修改了mysql的某個變量值,如果不退出session,重新連接,你用show variables 看到的還是修改之前的值,因為show variables 默認返回的是當前session的值,最好用show session variables 和 show global variables 來查看對應的變量值。
下面是個例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
mysql>
set
global auto_increment_increment=
2
;
Query OK,
0
rows affected (
0.00
sec)
mysql> show
var
iables like
'%auto_increment%'
;
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| auto_increment_increment |
1
|
| auto_increment_offset |
1
|
+--------------------------+-------+
2
rows
in
set
(
0.00
sec)
mysql> show session
var
iables like
'%auto_increment%'
;
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| auto_increment_increment |
1
|
| auto_increment_offset |
1
|
+--------------------------+-------+
2
rows
in
set
(
0.00
sec)
mysql> show global
var
iables like
'%auto_increment%'
;
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| auto_increment_increment |
2
|
| auto_increment_offset |
1
|
+--------------------------+-------+
2
rows
in
set
(
0.00
sec)
|
當然也可以只設定當前session有效
1
2
|
set
session auto_increment_increment=
2
;
set
session auto_increment_offset=
2
;
|
具體的例子:
auto_increment_increment=2
auto_increment_offset=1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
mysql> truncate t2;
Query OK,
0
rows affected (
0.00
sec)
mysql>
mysql>
mysql>
set
session auto_increment_increment=
2
;
Query OK,
0
rows affected (
0.00
sec)
mysql>
set
session auto_increment_offset=
1
;
Query OK,
0
rows affected (
0.00
sec)
mysql> show session
var
iables like
'%auto_incre%'
;
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| auto_increment_increment |
2
|
| auto_increment_offset |
1
|
+--------------------------+-------+
2
rows
in
set
(
0.00
sec)
mysql> insert into t2 values (
null
),(
null
),(
null
),(
null
),(
null
),(
null
);
Query OK,
6
rows affected (
0.00
sec)
Records:
6
Duplicates:
0
Warnings:
0
mysql> select * from t2;
+----+
| id |
+----+
|
1
|
|
3
|
|
5
|
|
7
|
|
9
|
|
11
|
+----+
6
rows
in
set
(
0.00
sec)
|
auto_increment_increment=2
auto_increment_offset=2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
mysql> truncate t2;
Query OK,
0
rows affected (
0.00
sec)
mysql>
mysql>
set
session auto_increment_increment=
2
;
Query OK,
0
rows affected (
0.00
sec)
mysql>
set
session auto_increment_offset=
2
;
Query OK,
0
rows affected (
0.00
sec)
mysql> show session
var
iables like
'%auto_incre%'
;
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| auto_increment_increment |
2
|
| auto_increment_offset |
2
|
+--------------------------+-------+
2
rows
in
set
(
0.00
sec)
mysql> insert into t2 values (
null
),(
null
),(
null
),(
null
),(
null
),(
null
);
Query OK,
6
rows affected (
0.00
sec)
Records:
6
Duplicates:
0
Warnings:
0
mysql> select * from t2;
+----+
| id |
+----+
|
2
|
|
4
|
|
6
|
|
8
|
|
10
|
|
12
|
+----+
6
rows
in
set
(
0.00
sec)
|
auto_increment_increment=10
auto_increment_offset=5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
mysql> truncate t2;
Query OK,
0
rows affected (
0.00
sec)
mysql>
set
session auto_increment_increment=
10
;
Query OK,
0
rows affected (
0.00
sec)
mysql>
set
session auto_increment_offset=
5
;
Query OK,
0
rows affected (
0.00
sec)
mysql> show session
var
iables like
'%auto_incre%'
;
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| auto_increment_increment |
10
|
| auto_increment_offset |
5
|
+--------------------------+-------+
2
rows
in
set
(
0.00
sec)
mysql> insert into t2 values (
null
),(
null
),(
null
),(
null
),(
null
),(
null
);
Query OK,
6
rows affected (
0.00
sec)
Records:
6
Duplicates:
0
Warnings:
0
mysql> select * from t2;
+----+
| id |
+----+
|
5
|
|
15
|
|
25
|
|
35
|
|
45
|
|
55
|
+----+
6
rows
in
set
(
0.00
sec)
|
一個很重要的問題:如果在原有的序列中強制插入一個值,比如上面的例子,下一個數據我插入57,那再往后生成的值會受前面插入數據的影響嗎?
答案是: 不會的!!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
mysql> insert into t2 values (
57
),(
58
);
Query OK,
2
rows affected (
0.01
sec)
Records:
2
Duplicates:
0
Warnings:
0
mysql> select * from t2;
+----+
| id |
+----+
|
5
|
|
15
|
|
25
|
|
35
|
|
45
|
|
55
|
|
57
|
|
58
|
+----+
8
rows
in
set
(
0.00
sec)
mysql> insert into t2 values (
null
),(
null
),(
null
);
Query OK,
3
rows affected (
0.00
sec)
Records:
3
Duplicates:
0
Warnings:
0
mysql> select * from t2;
+----+
| id |
+----+
|
5
|
|
15
|
|
25
|
|
35
|
|
45
|
|
55
|
|
57
|
|
58
|
|
65
|
|
75
|
|
85
|
+----+
11
rows
in
set
(
0.00
sec)
|
mysql> select * from test;
+----+------+
| id | name |
+----+------+
| 1 | haha |
| 2 | lala |
+----+------+
2 rows in set (0.00 sec)
mysql> show create table test\G;
*************************** 1. row ***************************
Table: test
Create Table: CREATE TABLE `test` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL,
PRIMARY KEY (`name`),
KEY `id` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
mysql> update test set id=5 where id=2;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> show create table test\G;
*************************** 1. row ***************************
Table: test
Create Table: CREATE TABLE `test` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL,
PRIMARY KEY (`name`),
KEY `id` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
變成了6,而不是原來的3
1、相關的參數:
show VARIABLES like '%auto_increment%';
auto_increment_increment
auto_increment_offset
可以通過set語句進行修改,但是重啟服務器之后會重新變為1
SET auto_increment_increment=2;
SET auto_increment_offset=5;
2、在MyISAM和Innodb兩種存儲引擎下二者的不同:
重啟服務器之后,Innodb類型系統會維護種子序列的最大值為當前數據的最大值,而MyISAM則保持與重啟前一致。