使用自增长字段为主键有不少问题,比如维护或是在大型分布应用中主键冲突的解决等。在一些大型分布应用中主键一般选用guid,这可以有效的避免主键冲突,减少对主键维护的工程。当然,对于中小型的应用,自增长字段的好处更多一些,简单、快速。
Sqlite中,一个自增长字段定义为INTEGER PRIMARY KEY AUTOINCREMENT,那么在插入一个新数据时,只需要将这个字段的值指定为NULL,即可由引擎自动设定其值,引擎会设定为最大的rowid+1。当然,也可以设置为非NULL的数字来自己指定这个值,但这样就必须自己小心,不要引起冲突。当这个rowid的值大于所能表达的最大值 9223372036854775807 (30及以后版本的rowid最大值)后,rowid的新值会这个最大数之前随机找一个没被使用了的值。所以在rowid达到最大值前,rowid的值是严格单调增加的。
INTEGER PRIMARY KEY AUTOINCREMENT 自增长字段的算法与rowid稍微有些不同。
第一,在达到最大值后,rowid会找已被删除的字段对应的rowid作为新值,而自增长字段则会丢出一个SQLITE_FULL的错误。
第二,自增长字段在增加新值时,是找一个从没被使用过的rowid作为新值,而rowid则是找最大已存在的rowid+1。这里对应用的影响会比较大,尤其是一些对id值有依赖的元记录,只适合使用自增长字段而不能用rowid。
比如,我们设计一个元记录表:
drop table test;
create table test (
[tkid] integer PRIMARY KEY autoincrement, -- 设置主键
[tktype] int default 0,
[tableid] varchar (50),
[createdate] datetime default (datetime('now', 'localtime')) -- 时间
);
第三,使用自增长字段,引擎会自动产生一个sqlite_sequence表,用于记录每个表的自增长字段的已使用的最大值,用户可以看到,并可以用使用 Update、Delete和Insert *** 作,但不建议这么使用,这会让引擎混乱。如果使用rowid,也会有这么一个内部表,用户可以维护rowid 值,但看不到。
这么看来,如果直接使用rowid来代替自增加字段,根据两者的细微的差别,需要注意是否与自己的应用冲突,如果没有冲突,那么用rowid会更快一点。
SQLite中创建自增字段:
简单的回答:一个声明为 INTEGER PRIMARY KEY 的字段将自动增加。
从 SQLite 的 234 版本开始,如果你将一个表中的一个字段声明为 INTEGER PRIMARY KEY,那么无论你何时向该表的该字段插入一个 NULL 值,这个 NULL 值将自动被更换为比表中该字段所有行的最大值大 1 的整数;如果表为空,那么将被更换为 1。
一个新的API函数 sqlite3_last_insert_rowid() 返回最近的插入 *** 作的整形键
注意这个整型键始终比之前插入表中的最后一个键大1。新键相对于表中的已有键来说是唯一的,但它可能与之前从表中删除的键值重叠。要始终得到在整个表中唯一的键,在INTEGER PRIMARY KEY的声明之前加关键词AUTOINCREMENT这样被选的键将总是比表中已存在的最大键大1。若可能的最大键已存在于表中,INSERT *** 作将失败并返回一个SQLITE_FULL错误码
SQLite数据库通常存储在单个普通磁盘文件中。但是,在某些情况下,数据库可能存储在内存中。
强制SQLite数据库单纯的存在于内存中的最常用方法是使用特殊文件名“ :memory: ” 打开数据库。换句话说,不是将真实磁盘文件的名称传递给sqlite3_open(),sqlite3_open16()或 sqlite3_open_v2()函数之一,而是传入字符串“:memory:”。例如:
调用此接口完成后,不会打开任何磁盘文件。而是在内存中创建一个新的数据库。数据库连接关闭后,数据库就不再存在。每一个memory数据库彼此不同。因此,打开两个数据库连接,每个数据库连接的文件名为“:memory:”,将创建两个独立的内存数据库。
特殊文件名“:memory:”可用于允许数据库文件名的任何位置。例如,它可以被用作 文件名 中的ATTACH命令:
请注意,为了应用特殊的“:memory:”名称并创建纯内存数据库,文件名中不能有其他文本。因此,可以通过添加路径名在文件中创建基于磁盘的数据库,如下所示: "/:memory:"。
使用URI文件名时,特殊的“:memory:”文件名也可以使用。例如:
要么,
如果使用URI文件名打开内存数据库,则允许它们使用共享缓存。如果使用未加修饰的“:memory:”名称来指定内存数据库,那么该数据库始终具有专用高速缓存,并且仅对最初打开它的数据库连接可见。但是,可以通过两个或多个数据库连接打开相同的内存数据库,如下所示:
要么,
这允许单独的数据库连接共享相同的内存数据库。当然,共享内存数据库的所有数据库连接都需要在同一个进程中。当数据库的最后一个连接关闭时,将自动删除数据库并回收内存。
如果在单个进程中需要两个或多个不同同时可共享的内存数据库,则mode = memory查询参数可与URI文件名一起使用以创建命名的内存数据库:
要么,
当以这种方式命名内存数据库时,它将仅与使用完全相同名称的另一个连接共享其缓存。
当传递给sqlite3_open()或 ATTACH的数据库文件的名称是空字符串时,则会创建一个新的临时文件来保存数据库。
每次都会创建一个不同的临时文件,因此就像使用特殊的“:memory:”字符串一样,两个到临时数据库的数据库连接都有自己的私有数据库。创建它们的连接关闭时,将自动删除临时数据库。
即使为每个临时数据库分配了磁盘文件,实际上临时数据库通常驻留在内存中的pager缓存中,因此“:memory:”创建的纯内存数据库与临时数据库之间的差别很小。由空文件名创建。唯一的区别是“:memory:”数据库必须始终保留在内存中,而如果数据库变大或SQLite受到内存压力,临时数据库的某些部分可能会刷新到磁盘。
前面的段落描述了默认SQLite配置下临时数据库的行为。如果需要,应用程序可以使用 temp_store编译指示和SQLITE_TEMP_STORE编译时参数来强制临时数据库表现为纯内存数据库。
虽然号称对Sqlite的使用有一年多的经验,但实际上并没有对Sqlite的各种语法有深入的了解,毕竟大多数时候选择Sqlite这种微型数据库,表结构设计上都十分的简单,一些复杂的sql *** 作很少会用到。另一方面Sqlite居然理论上可以支持2TB的数据,相信随着各路神仙对Sqlite的推崇,日后还是会大有作为的。
今天着重想谈一谈Sqlite中的Update。1
典型的Update(支持)UpdateT1SetColumn1 = v1,
Column2 =V2Wherekey = V3;
2Update…From(很不幸,
Sqlite是不支持的)UPDATEt1SETColumn1= t2 Column1FROMt2, t1WHEREt2key = t1key;
要进行表间更新
Update…From
,Sqlite里面有一个新鲜玩意
INSERT OR REPLACE
,跟Mysql类似,这个结构能够保证在存在的情况下替换,不存在的情况下更新,用这个机制就可以轻松实现
Update…From了。
INSERT OR REPLACE INTO
t1( key, Column1, Column2)SELECTt2key, t2 Column1,t2 Column2FROMt2, t1WHEREt2key = t1key;
备注:这种方法要避免插入 *** 作,首先要确保是依照主键执行的更新,如果where条件不是主键可能就有点麻烦了。
Update…where
寻求帮助了,下面是一个例子:UPDATEt1SETColumn1 = ( SELECT Columnx FROM t2 WHERE t2key =t1key ),
Column2 = ( SELECT Columny FROM t2 WHERE t2key =t1key ),
WHERE t1key = ( SELECT key FROM t2 WHERE t2key=t1key);
sqlite是文件型的数据库,所有的东西,都在一个文件中,故支持由对应的硬盘文件系统和 *** 作系统来决定
与 Oracle、MySQL、SQL Server 等数据库不同,它可以内嵌在程序中,是程序中的一个组成部分
以上就是关于SQLite数据库的id字段,怎么设置成从1开始自增全部的内容,包括:SQLite数据库的id字段,怎么设置成从1开始自增、SQLite 如何变成 内存数据库、Sqlite数据库的Update知多少等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)