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"): printrow
執行結果:
$ 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
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')
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的記錄,可以實現將所有表的自增欄位的取值歸零的效果(這種行為具有破壞性,請謹慎使用)。
實驗指令碼:
#!/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清空表並將自增列歸零》 。