Mysql中自增字段(AUTO_INCREMENT)的一些常識


原文鏈接:   http://naxieshir.com/fenlei/2/p/151.html


在系統開發過程中,我們經常要用到唯一編號。使用過mysql的人都應該知道,mysql有一個定義列為自增的屬性:AUTO_INCREMENT。


指定了AUTO_INCREMENT的列必須要建索引,不然會報錯,索引可以為主鍵索引,當然也可以為非主鍵索引。(不一定要做主鍵)

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字段

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的列,在插入時:

  1. 如果把一個NULL插入到一個AUTO_INCREMENT數據列里去,MySQL將自動生成下一個序列編號。編號從1開始,並1為基數遞增。

  2. 當插入記錄時,沒有為AUTO_INCREMENT明確指定值,則等同插入NULL值。

    mysql> 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)
  3. 上面語句等同於下面語句:

    mysql> insert into t5 (name) values ('test');
  4. 當插入記錄時,如果為AUTO_INCREMENT字段明確指定了一個數值,則會出現兩種情況:

       情況一,如果插入的值與已有的編號重復,則會出現出 錯信息,因為AUTO_INCREMENT數據列的值必須是唯一的;

       情況二,如果插入的值大於已編號的值,則會把該插入到數據列中,並使在下一個編號將從這個新值開始遞增。

    ## 初始表
    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

    換句話說,就是自增字段可以跳過一些編號

  5. 對於MyISAM表,如果用UPDATE命令更新自增列,如果列值與已有的值重復,則會出錯。如果大於已有值,則下一個編號從該值開始遞增。但是對於innodb表,update auto_increment字段,會導致發生報錯

    MyISAM表的update如下所示

    ## 當前狀態
    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會導致主鍵錯誤!

    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)
       
    ## 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之后會正常插入

    mysql> 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'


  6. 被delete語句刪除的id值,除非sql中將id重新插入,否則前面空余的id不會復用。

  7. delete from t3該語句不會引起auto_increment的變化,

    mysql> 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的變化,從頭開始。

    mysql> 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)


  8. last_insert_id()函數可獲得自增列自動生成的最后一個編號。但該函數只與服務器的本次會話過程中生成的值有關。如果在與服務器的本次會話中尚未生成AUTO_INCREMENT值,則該函數返回0。


修改AUTO_INCREMENT字段的起始值


   可用alter table table_name AUTO_INCREMENT=n命令來重設自增的起始值。

   但是如果設置的n比目前的數值小的話,執行的sql不會報錯,但是不會生效!MyISAM和Innodb均是如此。

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,.....]



查看當前值:

mysql> show variables 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來設置

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 來查看對應的變量值。

   下面是個例子:

mysql> set global auto_increment_increment=2;
Query OK, 0 rows affected (0.00 sec)
 
mysql> show variables like '%auto_increment%';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| auto_increment_increment | 1     |
| auto_increment_offset    | 1     |
+--------------------------+-------+
2 rows in set (0.00 sec)
 
mysql> show session variables like '%auto_increment%';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| auto_increment_increment | 1     |
| auto_increment_offset    | 1     |
+--------------------------+-------+
2 rows in set (0.00 sec)
 
mysql> show global variables like '%auto_increment%';       
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| auto_increment_increment | 2     |
| auto_increment_offset    | 1     |
+--------------------------+-------+
2 rows in set (0.00 sec)

當然也可以只設定當前session有效

set session auto_increment_increment=2;
set session auto_increment_offset=2;


具體的例子:


auto_increment_increment=2

auto_increment_offset=1

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 variables 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

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 variables 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

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 variables 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,那再往后生成的值會受前面插入數據的影響嗎?

答案是: 不會的!!

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)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM