zoukankan      html  css  js  c++  java
  • 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清空表并将自增列归零》

  • 相关阅读:
    代码面试最常用的10大算法
    ant google compiler 压缩
    美工资源
    面试题
    validate表单验证插件
    laypage分页
    layer弹出框小结
    Thymeleaf
    webApp开发
    grunt自动化构建工具
  • 原文地址:https://www.cnblogs.com/russellluo/p/3186786.html
Copyright © 2011-2022 走看看