SQLite中的自增關鍵字:AUTO_INCREMENT、INTEGER PRIMARY KEY與AUTOINCREMENT


1、SQLite不支持關鍵字AUTO_INCREMENT

1)AUTO_INCREMENT不生效的問題

SQL語句:

CREATE TABLE todo
(
    id INTEGER AUTO_INCREMENT,
    title TEXT,
    PRIMARY KEY (id)
);

問題描述:按照上述SQL語句創建表todo,用INSERT INTO todo (title) VALUES ('xxx')插入記錄,但查詢該記錄后得到的id為NULL(即Python中的None)

實驗腳本:

#!/usr/bin/python
# -*- encoding: utf-8 -*-

import sqlite3
con = sqlite3.connect(":memory:")

# 創建表
con.execute("""
CREATE TABLE todo
(
    id INTEGER AUTO_INCREMENT,
    title TEXT,
    PRIMARY KEY (id)
);""")

# 插入記錄
con.execute("INSERT INTO todo (title) VALUES ('shopping');")

# 查詢記錄
for row in con.execute("SELECT * FROM todo"):
    print row

運行結果:

$ python auto_increment_null.py 
(None, u'shopping')

2)AUTO_INCREMENT導致語法錯誤的問題

SQL語句:

CREATE TABLE todo
(
    id INTEGER PRIMARY KEY AUTO_INCREMENT,
    title TEXT
);

問題描述:根據SQL的語法,按理說上述SQL語句應該與1)中的SQL語句等效,但運行結果卻是語法錯誤

實驗腳本:

#!/usr/bin/python
# -*- encoding: utf-8 -*-

import sqlite3
con = sqlite3.connect(":memory:")

# 創建表
con.execute("""
CREATE TABLE todo
(
    id INTEGER PRIMARY KEY AUTO_INCREMENT,
    title TEXT
);""")

# 插入記錄
con.execute("INSERT INTO todo (title) VALUES ('shopping');")

# 查詢記錄
for row in con.execute("SELECT * FROM todo"):
    print row

運行結果:

$ python auto_increment_error.py 
Traceback (most recent call last):
  File "auto_increment_error.py", line 14, in <module>
    );""")
sqlite3.OperationalError: near "AUTO_INCREMENT": syntax error

上述兩個問題在《AUTO_INCREMENT in sqlite problem with python》中得到了解釋和解答:在SQLite中,自增字段需要使用關鍵字INTEGER PRIMARY KEY。

 

2、自增關鍵字INTEGER PRIMARY KEY

SQL語句:

CREATE TABLE todo
(
    id INTEGER PRIMARY KEY,
    title TEXT
);

或者

CREATE TABLE todo
(
    id INTEGER PRIMARY KEY NOT NULL,
    title TEXT
);

按照上述SQL語句創建表todo,用INSERT INTO todo (title) VALUES ('xxx')或者INSERT INTO todo (id, title) VALUES (NULL, 'xxx')插入記錄,查詢記錄后得到的id為自增的整型值。

實驗腳本:

#!/usr/bin/python
# -*- encoding: utf-8 -*-

import sqlite3
con = sqlite3.connect(":memory:")

# 創建表
con.execute("""
CREATE TABLE todo
(
    id INTEGER PRIMARY KEY,
    title TEXT
);""")

# 創建表:效果相同
'''
con.execute("""
CREATE TABLE todo
(
    id INTEGER PRIMARY KEY NOT NULL,
    title TEXT
);""")
'''

# 插入記錄:shopping
con.execute("INSERT INTO todo (title) VALUES ('shopping');")

# 插入記錄:working
con.execute("INSERT INTO todo (id, title) VALUES (NULL, 'working');")

# 查詢記錄
for row in con.execute("SELECT * FROM todo"):
    print row

運行結果:

$ python integer_primary_key_ok.py 
(1, u'shopping')
(2, u'working')

注意:之前看《No autoincrement for Integer Primary key in sqlite3》中有提到“SQLite的自增字段定義為NULL或NOT NULL是有區別的”,根據上面的實驗,這個問題好像已經不存在了。

 

3、關鍵字AUTOINCREMENT與內部表sqlite_sequence

SQLite中,在INTEGER PRIMARY KEY的基礎上添加AUTOINCREMENT后(即INTEGER PRIMARY KEY AUTOINCREMENT),可以在表的整個生命周期內保證“自增字段”的唯一性(create keys that are unique over the lifetime of the table)。

SQLite內部用一個叫作sqlite_sequence的表來保存所有表的自增字段的取值基准(the largest ROWID),如果清空sqlite_sequence的記錄,可以實現將所有表的自增字段的取值歸零的效果(這種行為具有破壞性,請謹慎使用)。

關於這一主題,更詳細的介紹可以參考《How do I create an AUTOINCREMENT field》《SQLite Autoincrement》

實驗腳本:

#!/usr/bin/python
# -*- encoding: utf-8 -*-

import sqlite3
con = sqlite3.connect(":memory:")

def new_and_show(tbl_name):
    """插入並顯示記錄"""
    # 插入記錄到表
    con.execute("INSERT INTO " + tbl_name + " (title) VALUES ('shopping');")
    # 查詢表記錄
    for row in con.execute("SELECT * FROM " + tbl_name):
        print row

def clr(tbl_name):
    """清除表記錄"""
    con.execute("DELETE FROM " + tbl_name)

print "--表todo--"
# 1. 創建表
con.execute("""
CREATE TABLE todo
(
    id INTEGER PRIMARY KEY,
    title TEXT
);""")
# 2. 插入並顯示記錄
new_and_show("todo")
# 3. 清除表記錄
clr("todo")
# 4. 插入並顯示記錄
new_and_show("todo")
# 5. 清除表記錄
clr("todo")
# 6. 插入並顯示記錄
new_and_show("todo")


print "--表todo_auto--"
# 1. 創建表
con.execute("""
CREATE TABLE todo_auto
(
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    title TEXT
);""")
# 2. 插入並顯示記錄
new_and_show("todo_auto")
# 3. 清除表記錄
clr("todo_auto")
# 4. 插入並顯示記錄
new_and_show("todo_auto")

# 將所有表的自增列都歸零
#clr("sqlite_sequence")

# 5. 清除表記錄
clr("todo_auto")
# 6. 插入並顯示記錄
new_and_show("todo_auto")

運行結果:

$ python autoincrement_diff.py 
--表todo--
(1, u'shopping')
(1, u'shopping')
(1, u'shopping')
--表todo_auto--
(1, u'shopping')
(2, u'shopping')
(3, u'shopping')

如果去掉clr("sqlite_sequence")這一行的注釋,則運行結果會變成:

$ python autoincrement_diff.py 
--表todo--
(1, u'shopping')
(1, u'shopping')
(1, u'shopping')
--表todo_auto--
(1, u'shopping')
(2, u'shopping')
(1, u'shopping')    ## 由於clr("sqlite_sequence")將表todo_auto的自增字段的取值歸零,因此這一行又變成了1

另外,SQLite不支持SQL標准語句“TRUNCATE TABLE tbl_name”,只能使用“DELETE FROM tbl_name”來刪除表記錄,具體可以參考《SQLite清空表並將自增列歸零》


免責聲明!

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



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