注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

民主与科学

独立之人格,自由之思想

 
 
 

日志

 
 

INTEGER PRIMARY KEY简介  

2010-06-18 13:38:56|  分类: 数据存储 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
 Sqlite 中INTEGER PRIMARY KEY AUTOINCREMENT和rowid/INTEGER PRIMARY KEY的使用
在用sqlite设计表时,每个表都有一个自己的整形id值作为主键,插入后能直接得到该主键.
因为sqlite内部本来就会为每个表加上一个rowid,这个rowid可以当成一个隐含的字段使用,
但是由sqlite引擎来维护的,在3.0以前rowid是32位的整数,3.0以后是64位的整数,可以使用这个内部的rowid作为每个表的
id主键
查了下文档:
参照http://www.sqlite.org/c3ref/last_insert_rowid.html
Each entry in an SQLite table has a unique 64-bit signed integer key called the "rowid". 
The rowid is always available as an undeclared column named ROWID, OID, 
or _ROWID_ as long as those names are not also used by explicitly declared columns. 
If the table has a column of type INTEGER PRIMARY KEY then that column is another alias for the rowid.
如果表中有个INTEGER PRIMARY KEY字段,那么它只是rowid的别名。
This routine returns the rowid of the most recent successful INSERT into the database from the database connection in the first argument. 
If no successful INSERTs have ever occurred on that database connection, zero is returned.
如果成功插入一条数据,会返回刚刚插入的数据的rowid.如果失败返回0.Android中如果发生错误返回的是-1
参照http://www.sqlite.org/faq.html
    Short answer: A column declared INTEGER PRIMARY KEY will autoincrement.
    Here is the long answer: If you declare a column of a table to be INTEGER PRIMARY KEY, 
    then whenever you insert a NULL into that column of the table,
    the NULL is automatically converted into an integer which is one greater than the largest value of that column over 
    all other rows in the table, or 1 if the table is empty. (If the largest possible integer key, 9223372036854775807, 
    then an unused key value is chosen at random.) For example, suppose you have a table like this:
        CREATE TABLE t1(
          a INTEGER PRIMARY KEY,
          b INTEGER
        );

    With this table, the statement
        INSERT INTO t1 VALUES(NULL,123);
    is logically equivalent to saying:
        INSERT INTO t1 VALUES((SELECT max(a) FROM t1)+1,123);
    There is a function named sqlite3_last_insert_rowid() which will return the integer key for the most recent insert operation.
    Note that the integer key is one greater than the largest key that was in the table just prior to the insert. 
    The new key will be unique over all keys currently in the table, 
    but it might overlap with keys that have been previously deleted from the table. 
    To create keys that are unique over the lifetime of the table, 
    add the AUTOINCREMENT keyword to the INTEGER PRIMARY KEY declaration. 
    Then the key chosen will be one more than than the largest key that has ever existed in that table. 
    If the largest possible key has previously existed in that table, then the INSERT will fail with an SQLITE_FULL error code.
把一个列申明为INTEGER PRIMARY KEY,那么在向它插入NULL,该列就由系统指定。该值为已经存在的数据的该列的最大值加1。空表时该值就为1
如果该值已经超过了最大值,那么它会随即选择一个已存数据没使用过的值做个插入数据的值。
如果用户在插入时给它指定一个值,那么返回的也是那个值。

因为本来返回的应该是rowid,但如果表中有个INTEGER PRIMARY KEY字段,那么它只是rowid的别名。
所以返回的就是指定的那个值。
把一个列声明为
INTEGER PRIMARY KEY AUTOINCREMENT的话,它的值是选择的在该表中曾经使用过的最大值+1。
如果达到了最大值的话,会插入失败,并抛出an SQLITE_FULL error code。

再参照sqlite的文档:
http://www.sqlite.org/autoinc.html
最后得出以下结论
用自增长字段为主键有不少问题,比如维护或是在大型分布应用中主键冲突的解决等。在一些大型分布应用中主键一般选用 guid,这可以有效的避免主键冲突,减少对主键维护的工程
当然,对于中小型的应用,自增长字段的好处更多一些,简单、快速。

Sqlite中,一个自增长字段定义为INTEGER PRIMARY KEY AUTOINCREMENT或者INTEGER PRIMARY KEY时 ,那么在插入一个新数据时,只需要将这个字段的值指定为NULL,即可由引擎自动设定其值。
当然,也可以设置为非 NULL的数字来自己指定这个值,但这样就必须自己小心,不要引起冲突。

对于INTEGER PRIMARY KEY ,当这个rowid的值大于所能表达的最大值 9223372036854775807 (3.0及以后版本的rowid最大值)后,rowid的新值会这个最大数之前随机找一个没被使用了的值。
所以在rowid达到最大值前,rowid的值是严格单调增加的。
INTEGER PRIMARY KEY AUTOINCREMENT 自增长字段的算法与rowid/INTEGER PRIMARY KEY稍微有些不同。
第一,在达到最大值后,rowid/INTEGER PRIMARY KEY会找已被删除的字段对应的rowid/INTEGER PRIMARY KEY作为新值,
而自增长字段INTEGER PRIMARY KEY AUTOINCREMENT则会丢出一个SQLITE_FULL的错误。
第二,自增长字段INTEGER PRIMARY KEY AUTOINCREMENT在增加新值时,是找一个从没被使用过的值作为新值,而 rowid/INTEGER PRIMARY KEY则是找最大已存在的(rowid/INTEGER PRIMARY KEY)+1
这里对应用的影响会比较大,尤其是一些对id值有依赖的元记录,只适合使用自增长字段而不能用rowid/INTEGER PRIMARY KEY。
比如,我们设计一个元记录表:
Create table meta_struct(id INTEGER PRIMARY KEY AUTOINCREMENT, name varchar, type Integer);
然后,定义一个一级表,来描述其它表的结构:
Create table meta_table(tableid INTEGER, table_field integer)
最后,我们的应用可以根据这个一级表来产生实际使用的二级表。
这样为保证兼容性meta_struct中的id必须是唯一的,如果有字段被删除,也不能重复使用这个字段的id值,不然,在数据库合并时,一级表和二级表就会混乱。
所以meta_struct表中的主键只能使用自增长字段,而不能用rowid。
第三使用自增长字段INTEGER PRIMARY KEY AUTOINCREMENT引擎会自动产生一个sqlite_sequence表,用于记录每个表的自增长字段的已使用的最大值,
用户可以看到,并可以用使用Update、Delete和Insert操作,但不建议这么使用,这会让引擎混乱。
如果使用
rowid/INTEGER PRIMARY KEY,也会有这么一个内部表,用户可以维护rowid/INTEGER PRIMARY KEY值,但看不到。
这么看来,如果直接使用
rowid/INTEGER PRIMARY KEY来代替自增加字段,根据两者的细微的差别,需要注意是否与自己的应用冲突,
如果没有冲突,那么用
rowid/INTEGER PRIMARY KEY会更快一
第四在android中,对于INTEGER PRIMARY KEY
如果插入数据A,B,C,它们的_id为1,2,3,那么如果把他们都删除了,再插入一条数据,那么它的id为1而不是4。
  评论这张
 
阅读(2795)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017