• SQLite 使用主键,ROWID 及自增列


    SQLite 使用主键,ROWID 及自增列

    之前关注过一些嵌入式数据库,倒时 SQLite 风头更劲,在 Android 上被应用,在 HTML5 中一些浏览器的 Local Database 的实现也是 SQLite。因在 PhoneGap 中使用数据库存储的选择也期待着它的表现,首先要建个数据库,第一要义就是主键的选择,自增列是最有效更简单的。

    这里就看下 SQLite 怎么使用自动列,了解三个内容,ROWID, ROWID 的别名,自动列与序列表,归根结底它们都是 ROWID。

    1. ROWID

    每个表默认都有 rowid 列,除非创建表时指定了 WITHOUT ROWID, 它现在是 64 位长的。在查询时用 select * from table1 里没有它,要显式的用 select rowid, * from table1 就会列出它来。

    2. ROWID 的别名

    ROWID 除了可用 rowid 查出它之外,还可用别名 _ROWID_ 和 OID,都不分大小写的, 例如 select oid from table1。另外我们还可以自定义一个 ROWID 的别名,用 INTEGER PRIMARY KEY 标识的列也是 ROWID 的一个别名,比如我们用 id 来作为 ROWID 的别名。

    ROWID 的表示也是个自增列,每个表有自己的计数器,和常见的数据库的自增列是一致的。

    SQLite 的 ROWID 可不象 Oracle 的 ROWID, Oracle 的 ROWID 是纯内部的,标记着记录的物理位置,所以数据库导入导出 Oracle 的 ROWID 就会变了。更为可怕的是 SQLite 的 ROWID 是可以自己赋值的。

    3. 自增列序列表(也是 ROWID)

    用 INTEGER PRIMARY KEY AUTOINCREMENT 标识的列就是个自增列,说到底它也是 ROWID  别名。数据库中存在自增列后,SQLite 就会创建一个 sqlite_sequence 表。所有表的自增列都共享这个表,sqlite_sequence 分别维护着每个自增列的当前值,所以自增列的计数也是单独的。它不象于 Oracle 中多个表在共用一个序列时,ID 值是交错的,Oracle 的序列的好处就是插入前可获知下一个序列值。

    自增列的好处就能查看到当前的序列值,sqlite_sequence 中的值也是可以修改的,不过一般人不会这么干,可以用 select last_insert_rowid() 得到刚刚插入的 ROWID 值。

    4. VACUUM 命令

    VACUUM 能重建 ROWID 值,比如对于非自增列,select rowid, c1

    1|a
    2|b
    3|c

    把中间那条记录删除后,select rowid, c1 后的记录是

    1|a
    3|c

    这个结果我们没什么惊奇的,现在我们来执行下 vacuum 命令,再 select rowid, c1 后记录是

    1|a
    2|b

    ROWID 又可重复利用了,但命令 vacuum 对于自增列是不起作用的,因为自增列的值是由 sqlite_sequence 表维护的。

    下面是演示那几个概念的全过程:

    SQLite version 3.8.2 2013-12-06 14:53:3
    Enter ".help" for instructions
    Enter SQL statements terminated with a ";"
    sqlite> create table t1(c1);
    sqlite> create table t2(c1);
    sqlite> insert into t1(c1) values('a');
    sqlite> insert into t2(c1) values('b');
    sqlite> select * from t1;
    a
    sqlite> insert into t2(oid, c1) values(5, 'c');
    sqlite> select rowid, * from t1 union select rowid, * from t2;
    1|a
    1|b
    5|c
    sqlite> create table t3(c1 integer primary key, c2);
    sqlite> insert into t3(c2) values('c');
    sqlite> select rowid, * from t3;
    1|1|c
    sqlite> select rowid, _rowid_, oid, * from t3;
    1|1|1|1|c
    sqlite> select 8 from sqlite_master;
    sqlite> select * from sqlite_master;
    table|t1|t1|2|CREATE TABLE t1(c1)
    table|t2|t2|3|CREATE TABLE t2(c1)
    table|t3|t3|4|CREATE TABLE t3(c1 integer primary key, c2)
    sqlite> create table t4(c1 integer primary key autoincrement, c2);
    sqlite> select * from sqlite_master;
    table|t1|t1|2|CREATE TABLE t1(c1)
    table|t2|t2|3|CREATE TABLE t2(c1)
    table|t3|t3|4|CREATE TABLE t3(c1 integer primary key, c2)
    table|t4|t4|5|CREATE TABLE t4(c1 integer primary key autoincrement, c2)
    table|sqlite_sequence|sqlite_sequence|6|CREATE TABLE sqlite_sequence(name,seq);
    sqlite> insert into t4(c2) values('d');
    sqlite> select rowid, * from t4;
    1|1|d
    sqlite> select * from sqlite_sequence;
    t4|1
    sqlite> create table t5(c1 integer primary key autoincrement, c2);
    sqlite> select * from sqlite_sequence;
    t4|1
    sqlite> insert into t5(c2) values('e');
    sqlite> select * from sqlite_sequence;
    t4|1
    t5|1
    sqlite> insert into t1(c1) values('f');
    sqlite> delete from t1 where rowid=1;
    sqlite> select rowid, * from t1;
    1|f
    sqlite> update sqlite_sequence set seq=4 where name='t5';
    sqlite> insert into t5(c2) values('h');
    sqlite> select * from t5;
    1|e
    4|h
    sqlite> delete from t5 where c1=1;
    sqlite> select * from t5
    4|h

    参考:1. SQLite Autoincrement
            2. sqlite_sequence table

  • 相关阅读:
    java图片加文字
    [转]NetBeans优化技巧 提升启动速度
    重建win7桌面图标缓存
    负载测试(Load Test)
    乐观锁与悲观琐的区别
    事物锁表问题
    建立silverlight安装环境
    持续集成ccnet
    C# AppDomain
    Windows Services
  • 原文地址:https://www.cnblogs.com/z5337/p/3637388.html
Copyright © 2020-2023  润新知