写在前面:
本文章旨在总结备份、方便以后查询,由于是个人总结,如有不对,欢迎指正;另外,内容大部分来自网络、书籍、和各类手册,如若侵权请告知,马上删帖致歉。
目录
- [SQLite 类型](#SQLite 类型)
- 数据表查询
- [C / C++ 接口函数](#C / C++ 接口函数)
-
- [Errors 码](#Errors 码)
- [API 函数](#API 函数)
- 操作流程
- 常用命令
- 参考
首发及后期更新将于 https://arachnid.cc/sqlite-summarize/,此处仅作二次备份。
SQLite 类型
1、存储类
SQLite 存储类属性划分为以下几种类型:
类型 | 描述 |
---|---|
NULL | 表示该值为 NULL 值。 |
INTEGER | 无符号整型值,根据值的大小存储在 1、2、3、4、6 或 8 字节中。 |
REAL | 浮点值,存储为 8 字节的 IEEE 浮点数字。 |
TEXT | 文本字符串,使用 UTF-8、UTF-16BE 或 UTF-16LE 编码方式存储。 |
BLOB | 存储 Blob 数据,该类型数据和输入数据完全相同。 |
2、数据类型
-
布尔数据类型:
SQLite 并没有提供专门的布尔存储类型,取而代之的是存储整型 1 表示 true,0 表示 false。
-
日期和时间数据类型:
和布尔类型一样,SQLite 也同样没有提供专门的日期时间存储类型,而是以 TEXT、REAL 和 INTEGER 类型分别不同的格式表示该类型,如:
TEXT : "YYYY-MM-DD HH:MM:SS.SSS"。
REAL :以 Julian 日期格式存储。
INTEGER :以 Unix 时间形式保存数据值,即从 1970-01-01 00:00:00 到当前时间所流经的秒数。
3、类型亲缘性(Type Affinity)
为了最大限度地提高 SQLite 和其他数据库引擎之间的兼容性,SQLite 支持 "类型亲缘性" 的概念。使其它 SQL 数据库引擎能在 SQLite 上运行;在表字段被声明之后,SQLite 都会根据该字段声明时的类型为其选择一种亲缘类型,当数据插入时,该字段的数据将会优先采用亲缘类型作为该值的存储方式,除非亲缘类型不匹配或无法转换当前数据到该亲缘类型,这样 SQLite 才会考虑其它更适合该值的类型存储该值。
SQLite 3 数据库中支持分配的类型关联:
- TEXT
- NUMERIC
- INTEGER
- REAL
- BLOB
决定规则:
- 如果声明的类型包含字符串 "INT",则它分配为
INTEGER
。 - 如果声明的类型包含任意字符串 "CHAR"、"CLOB" 或 "TEXT" 的关键字,则被分配为
TEXT
。请注意,VARCHAR 类型包含字符串 "CHAR",因此被分配为TEXT
。 - 如果声明的类型包含字符串 "BLOB",或者如果未指定类型,则被分配为
BLOB
。 - 如果声明的类型包含任意字符串 "REAL"、"FLOA" 或 "DOUB" 的关键字,则被分配为
REAL
。 - 其余情况下,归类为
NUMERIC
。
note:请注意,确定类型亲缘性的规则顺序很重要。声明类型为 "CHARINT" 的字段将同时匹配规则 1 和 2,但第一条规则采用优先权,所以会被分配为 INTEGER
。
示例:
声明的类型 | 类型亲缘性 | 规则优先级 |
---|---|---|
INT INTEGER TINYINT SMALLINT MEDIUMINT BIGINT UNSIGNED BIG INT INT2 INT8 | INTEGER | 1 |
CHARACTER(20) VARCHAR(255) VARYING CHARACTER(255) NCHAR(55) NATIVE CHARACTER(70) NVARCHAR(100) TEXT CLOB | TEXT | 2 |
BLOB no datatype specified | BLOB | 3 |
REAL DOUBLE DOUBLE PRECISION FLOAT | REAL | 4 |
NUMERIC DECIMAL(10,5) BOOLEAN DATE DATETIME | NUMERIC | 5 |
数据表查询
1、查看所有表名
SELECT * FROM sqlite_master WHERE type='table' ORDER BY name;
sqlite_master 是一个特殊表, 属于系统表;存放在根页中,每一个数据库的 .db
文件都有一个 sqlite_master 表。该表存放了 .db
中所有表的相关信息,并只有只读权限,写操作由系统自动执行,使用者没有写的执行权限;其结构如下:
c
CREATE TABLE sqlite_master (
type TEXT, // 记录项目的类型,如:表(table), 索引(index), 视图(view), 触发器(trigger)
name TEXT, // 记录项目的名称,如表名、索引名等
tbl_name TEXT, // 记录所从属的表名,如索引所在的表名。对于表来说,该列就是表名本身
rootpage INTEGER, // 记录项目在数据库页中存储的编号。对于视图和触发器,该列值为 0 或者 NULL
sql TEXT // 记录创建该项目的 SQL 语句
);
2、查看表的字段
PRAGMA table_info(table_name);
其中 [table_name] 为待查数据表名。
3、查看整表数据
SELECT * FROM table_name;
其中 [table_name] 为待查数据表名。
note:参数传入,字符串用单引号包括。
C / C++ 接口函数
Errors 码
c
#define SQLITE_OK 0 /* 成功 */
/* 错误码 */
#define SQLITE_ERROR 1 /* sql错误或丢失的数据库,SQL error or missing database */
#define SQLITE_INTERNAL 2 /* sqlite内部逻辑错误,Internal logic error in SQLite */
#define SQLITE_PERM 3 /* 拒绝访问,Access permission denied */
#define SQLITE_ABORT 4 /* 回调函数请求取消操作,Callback routine requested an abort */
#define SQLITE_BUSY 5 /* 数据库文件被锁定,The database file is locked */
#define SQLITE_LOCKED 6 /* 数据库的一个表被锁定,A table in the database is locked */
#define SQLITE_NOMEM 7 /* 某次malloc函数调用失败,A malloc() failed */
#define SQLITE_READONLY 8 /* 尝试写入一个只读数据库,Attempt to write a readonly database */
#define SQLITE_INTERRUPT 9 /* 操作sqlite3_interrupt函数被中断,Operation terminated by sqlite3_interrupt()*/
#define SQLITE_IOERR 10 /* 发生磁盘I/O错误,Some kind of disk I/O error occurred */
#define SQLITE_CORRUPT 11 /* 数据库磁盘映像不正确,The database disk image is malformed */
#define SQLITE_NOTFOUND 12 /* 找不到表或记录,NOT USED. Table or record not found */
#define SQLITE_FULL 13 /* 数据库满而插入失败,Insertion failed because database is full */
#define SQLITE_CANTOPEN 14 /* 无法打开数据库,Unable to open the database file */
#define SQLITE_PROTOCOL 15 /* 数据库锁定协议错误,NOT USED. Database lock protocol error */
#define SQLITE_EMPTY 16 /* 数据库为空,Database is empty */
#define SQLITE_SCHEMA 17 /* 数据库结构发生改变,The database schema changed */
#define SQLITE_TOOBIG 18 /* 数据大小超限,String or BLOB exceeds size limit */
#define SQLITE_CONSTRAINT 19 /* 约束违反,Abort due to constraint violation */
#define SQLITE_MISMATCH 20 /* 数据类型不匹配,Data type mismatch */
#define SQLITE_MISUSE 21 /* 库使用不正确,Library used incorrectly */
#define SQLITE_NOLFS 22 /* 使用了操作系统不支持的功能,Uses OS features not supported on host */
#define SQLITE_AUTH 23 /* 授权失败,Authorization denied */
#define SQLITE_FORMAT 24 /* 附加数据库格式错误,Auxiliary database format error */
#define SQLITE_RANGE 25 /* sqlite3_bind的第2给参数超出范围,2nd parameter to sqlite3_bind out of range */
#define SQLITE_NOTADB 26 /* 不是数据库文件,File opened that is not a database file */
#define SQLITE_NOTICE 27 /* Notifications from sqlite3_log() */
#define SQLITE_WARNING 28 /* Warnings from sqlite3_log() */
#define SQLITE_ROW 100 /* sqlite3_step产生一个就绪行,sqlite3_step() has another row ready */
#define SQLITE_DONE 101 /* sqlite3_step执行完成,sqlite3_step() has finished executing */
API 函数
以下只列举嵌入式环境下常用的 API:
sqlite3_open
c
SQLITE_API int sqlite3_open(
const char *filename, /* Database filename (UTF-8) */
sqlite3 **ppDb /* OUT: SQLite db handle */
);
该函数用于打开由 filename
参数指定的 SQLite 数据库文件,并返回一个 *ppDb
数据库连接句柄,即使发生错误;filename
为 UTF-8 编码,如果 SQLite 无法分配内存来保存 sqlite3 对象,则会在 *ppDb
中写入一个 NULL,而不是指向 sqlite3 对象的指针。如果数据库成功打开,则返回 SQLITE_OK。否则返回错误代码。sqlite3_errmsg() 可用于获取任何 sqlite3_open() 执行失败后错误的英文描述。
如果 filename
参数是 ':memory:'
,那么 sqlite3_open() 将会在 RAM 中创建一个内存数据库,这只会在数据库连接关闭前持续。
如果 filename
参数是 ''
(空字符串),则将创建一个专用的临时磁盘数据库;一旦数据库连接关闭,此专用数据库将被自动删除。
sqlite3_close
c
SQLITE_API int sqlite3_close(sqlite3*);
该函数与 sqlite3_open 函数相对应,用于关闭之前调用 sqlite3_open() 打开的数据库连接,此时所有与连接相关的语句都应在连接关闭之前完成。
如果还有查询没有完成,sqlite3_close() 将返回 SQLITE_BUSY 禁止关闭的错误消息;当成功执行,将销毁 sqlite3 对象并释放所有关联资源时返回 SQLITE_OK。
sqlite3_exec
c
SQLITE_API int sqlite3_exec(
sqlite3*, /* An open database */
const char *sql, /* SQL to be evaluated */
int (*callback)(void*,int,char**,char**), /* Callback function */
void *, /* 1st argument to callback */
char **errmsg /* Error msg written here */
);
sqlite3_exec() 提供了一个执行 SQL 命令的快捷方式,SQL 命令由 *sql
参数提供;它是 sqlite3_prepare_v2() 、sqlite3_step() 和 sqlite3_finalize() 的包装函数,允许应用程序运行多个 SQL 语句,而无需编写大量 C 代码。
sqlite3_exec() 程序解析并执行由 *sql
参数所给的每个命令,直到字符串结束或者遇到错误为止。此参数等同于使用 shell 实现所有的 sqlite 功能命令,所以这个 *sql
就是对应 sqlite 功能命令的 "字符串"。
callback
是执行 *sql
对应的功能命令后,所调取的函数,即回调函数;用于将执行结果进行分析处理。其原型如下:
typedef int (*sqlite3_callback)(void *data, int argc, char **argv, char **azColName);
sqlite3_callback 参数:
- data:由 sqlite3_exec 传入的参数
void*
,或者说是指针参数。 - argc:查询到的这一条记录由多少个字段(多少列)。
- argv:该参数是双指针,查询出来的数据都保存在这里,它是一个一维数组,每一个元素都是一个
char*
,是一个字段内容,所以这个参数就可以不是单字节,而是可以为字符串等不定长度的数值,用字符串表示,以'\0'
结尾。 - azColName:该参数是双指针,与
argv
是对应的,表示这个字段的字段名称。
note:除 data
传入参数外,回调函数的其它参数一定是 SQL 命令执行结果的进一步处理;此外,需要特别注意的是:回调函数多数时候不是执行 1 次,而是会循环执行 n 次,例如当我们执行 SELECT 命令时,往往输出的结果会是多行,假设有 n 行,那么就会执行 n 次回调函数。
实例:
c
#include <stdio.h>
#include <sqlite3.h>
static int callback(void *NotUsed, int argc, char **argv, char **azColName){
int i;
for(i=0; i<argc; i++){
printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
}
printf("\n");
return 0;
}
int main(int argc, char **argv){
sqlite3 *db;
char *zErrMsg = 0;
int rc;
if( argc!=3 ){
fprintf(stderr, "Usage: %s DATABASE SQL-STATEMENT\n", argv[0]);
return(1);
}
rc = sqlite3_open(argv[1], &db);
if( rc ){
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
return(1);
}
rc = sqlite3_exec(db, argv[2], callback, NULL, &zErrMsg);
if( rc!=SQLITE_OK ){
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
}
sqlite3_close(db);
return 0;
}
sqlite3_get_table
c
SQLITE_API int sqlite3_get_table(
sqlite3 *db, /* An open database */
const char *zSql, /* SQL to be evaluated */
char ***pazResult, /* Results of the query */
int *pnRow, /* Number of result rows written here */
int *pnColumn, /* Number of result columns written here */
char **pzErrmsg /* Error msg written here */
);
在最新的文档中,表明这该函数是一个传统的 API,保留该 API 是为了向后兼容;因此,不建议使用此接口。
输入参数:
-
db:打开数据库文件后返回的句柄。
-
zSql:需要执行的 SQL 命令字符串。
-
pazResult:对字符串数组的引用。使用此引用传回查询结果。传回的值必须通过调用
sqlite3_free_table()
。 -
pnRow:查询返回的行数,不包括列名。
-
pnColumn:查询返回的列数。
-
pzErrmsg:对字符串的可选引用。如果发生错误,引用将被设置为一条错误消息。该应用程序负责 释放的消息
sqlite3_free()
。如果没有错误发生,引用将被设置为 NULL。引用可能为 NULL。
和 sqlite3_exec() 这种使用回调函数的方式不同,sqlite3_get_table() 的功能要显得更加简便。它通过控制语句的传入,直接将参数赋值给指针传出。
note:虽然 sqlite3_get_table() 的使用较于 sqlite3_exec() 更为简便,但官方不推荐使用的,在实际当中它更趋于用作测试 API,并且根据官方建议,推荐使用 sqlite3_prepare_v2()、sqlite3_column_xxx() 这些 API 组合。
sqlite3_free_table
c
SQLITE_API void sqlite3_free_table(char **result);
该函数与 sqlite3_get_table 函数相对应,在应用程序完成 sqlite3_get_table 的结果使用后,它必须将查询结果的指针 pazResult
传递给 sqlite3_free_table() 以释放分配的内存。
sqlite3_prepare_v2
c
SQLITE_API int sqlite3_prepare_v2(
sqlite3 *db, /* Database handle */
const char *zSql, /* SQL statement, UTF-8 encoded */
int nByte, /* Maximum length of zSql in bytes. */
sqlite3_stmt **ppStmt, /* OUT: Statement handle */
const char **pzTail /* OUT: Pointer to unused portion of zSql */
);
输入参数:
- db:从先前成功调用 sqlite3_open()、sqlite3_open v2()或sqlite3_open16()获得的 SQLite 数据库。
- zSql:要执行的 SQL 语句(可以包含未赋值的变量)
- nByte:如果
nByte
参数为负,则zSql
被读取到第一个空结束终止符。如果nByte
为正,则它是从zSql
读取的字节数。 - ppStmt:解析编译出的 SQL 语句实例。
- pzTail:如果
pzTail
不为空,那么*pzTail
将指向zSql
中第一个 SQL 语句结束后的第一个字节。
sqlite3_bind_xxx
c
SQLITE_API int sqlite3_bind_blob( sqlite3_stmt* stmt, int pidx, const void* val, int bytes, mem_callback);
SQLITE_API int sqlite3_bind_blob64( sqlite3_stmt* stmt, int pidx, const void* val, sqlite3_uint64 bytes, mem_callback);
SQLITE_API int sqlite3_bind_double( sqlite3_stmt* stmt, int pidx, double val);
SQLITE_API int sqlite3_bind_int( sqlite3_stmt* stmt, int pidx, int val);
SQLITE_API int sqlite3_bind_int64( sqlite3_stmt* stmt, int pidx, sqlite3_int64 val);
SQLITE_API int sqlite3_bind_null( sqlite3_stmt* stmt, int pidx);
SQLITE_API int sqlite3_bind_text( sqlite3_stmt* stmt, int pidx, const char* val, int bytes, mem_callback);
SQLITE_API int sqlite3_bind_text16( sqlite3_stmt* stmt, int pidx, const void* val, int bytes, mem_callback);
SQLITE_API int sqlite3_bind_text64( sqlite3_stmt* stmt, int pidx, const char* val, sqlite3_uint64 bytes, mem_callback, unsigned char encoding);
SQLITE_API int sqlite3_bind_value( sqlite3_stmt* stmt, int pidx, const sqlite3_value* val);
// SQLITE_API int sqlite3_bind_pointer( sqlite3_stmt*, int, void*, const char*,void(*)(void*));
SQLITE_API int sqlite3_bind_zeroblob( sqlite3_stmt* stmt, int pidx, int bytes);
SQLITE_API int sqlite3_bind_zeroblob64(sqlite3_stmt* stmt, int pidx, sqlite3_uint64 bytes);
void mem_callback( void* ptr );
用于绑定任何参数值。
- stmt:指向一个被 sqlite3_prepare_v2() 等接口编译的语句句柄,它可被 sqlite3_step() 执行。最后用 sqlite3_finalize() 来释放它。
- pidx:SQL 参数(每列元素)的索引值,参数索引值从 1 开始。
- val:要绑定的数据值。
- bytes:数据值的大小,以字节(不是字符)为单位。通常,长度不包括任何空结束符。如果
val
是一个以空结束的字符串,把该值设为为负值(-1),则会自动计算长度。 - mem_callback:一个指向内存释放函数的函数指针。此函数用于在 SQLite 处理完BLOB 或 string 之后对其进行处理,主要用来释放
val
的内存缓冲区;如果缓冲区是用 sqlite3_malloc() 分配的,则可以直接传递对 sqlite3_free() 的引用。也可以使用特殊标志SQLITE_STATIC
和SQLITE_TRANSIENT
;SQLITE_STATIC
说明数据值为常量,位于静态的非托管空间中,不需要释放,而SQLITE_TRANSIENT
会使得对val
数据做一份拷贝。
sqlite3_step
c
SQLITE_API int sqlite3_step(sqlite3_stmt*);
在调用 sqlite3_prepare_v2() 等接口编译的语句句柄后,必须调用此函数一次或多次以计算语句。
返回值:
-
SQLITE_BUSY:忙碌,数据库引擎无法锁定数据去完成其工作。可以重试该语句。
-
SQLITE_DONE:意味着 SQL 语句执行完成且成功。一旦执行成功后,sqlite3_step() 就不应该被再次调用执行,除非我们使用 sqlite3_reset() 重置
sqlite3_stmt
数据。 -
SQLITE_ROW:当返回的行数据较多时会出现,代表获得了一条有效数据行,此时可以通过 sqlite3_column_xxx 函数来取得数据;再次调用 sqlite3_step() 可取得下一条查询结果,直至返回
SQLITE_DONE
。 -
SQLITE_ERROR:表示发生了运行时错误(例如约束冲突),此时可以通过 sqlite3_errmmsg() 取得相关的错误信息,并且不应再次调用 sqlite3_step() 。
-
SQLITE_MISUSE:意味着这个例程被不适当地调用。可能是在已完成的准备好的语句上调用的,也可能是在以前返回
SQLITE_ERROR
或SQLITE_DONE
的语句上调用的。或者可能是同一数据库连接同时被两个或多个线程使用。
sqlite3_column_xxx
c
SQLITE_API const void* sqlite3_column_blob( sqlite3_stmt* stmt, int cidx);
SQLITE_API double sqlite3_column_double( sqlite3_stmt* stmt, int cidx);
SQLITE_API int sqlite3_column_int( sqlite3_stmt* stmt, int cidx);
SQLITE_API sqlite3_int64 sqlite3_column_int64( sqlite3_stmt* stmt, int cidx);
SQLITE_API const unsigned char* sqlite3_column_text( sqlite3_stmt* stmt, int cidx);
SQLITE_API const void* sqlite3_column_text16(sqlite3_stmt* stmt, int cidx);
SQLITE_API sqlite3_value* sqlite3_column_value( sqlite3_stmt* stmt, int cidx);
SQLITE_API int sqlite3_column_bytes( sqlite3_stmt* stmt, int cidx);
SQLITE_API int sqlite3_column_bytes16(sqlite3_stmt* stmt, int cidx);
SQLITE_API int sqlite3_column_type( sqlite3_stmt* stmt, int cidx);
用于从当前结果行中提取列值。
- stmt:指向一个被 sqlite3_prepare_v2() 等接口编译的语句句柄,它可被 sqlite3_step() 执行。最后用 sqlite3_finalize() 来释放它。
- cidx:SQL 参数(每列元素)的索引值,参数索引值从 0 开始。
返回结果:
API 函数 | 结果值 | |
---|---|---|
sqlite3_column_blob | → | BLOB |
sqlite3_column_double | → | REAL |
sqlite3_column_int | → | 32 位 INTEGER |
sqlite3_column_int64 | → | 64 位 INTEGER |
sqlite3_column_text | → | UTF-8 TEXT |
sqlite3_column_text16 | → | UTF-16 TEXT |
sqlite3_column_value | → | 作为 未受保护的 sqlite3_value 对象 |
sqlite3_column_bytes | → | BLOB 或 UTF-8 TEXT 的字节大小 |
sqlite3_column_bytes16 | → | UTF-16 TEXT 的字节大小 |
sqlite3_column_type | → | 默认数据的类型 |
sqlite3_reset
c
SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
用于重置 sqlite3_stmt
数据,然后准备被重新执行。任何使用 sqlite3_bind_xxx 函数将值绑定到它们的 SQL 语句变量都将保留它们的值。使用 sqlite3_clear_bindings() 重置绑定。
返回值:
- SQLITE_BUSY
- SQLITE_DONE
- SQLITE_ROW
操作流程
使用 SQLite 数据库,最典型的函数操作流程(伪代码):
c
/* create a statement from an SQL string */
sqlite3_stmt *stmt = NULL;
if ( sqlite3_prepare_v2( db, sql_str, sql_str_len, &stmt, NULL ) == SQLITE_OK )
{
/* use the statement as many times as required */
while( ... )
{
/* bind any parameter values */
sqlite3_bind_xxx( stmt, param_idx, param_value... );
...
/* execute statement and step over each row of the result set */
while ( sqlite3_step( stmt ) == SQLITE_ROW )
{
/* extract column values from the current result row */
col_val = sqlite3_column_xxx( stmt, col_index );
...
}
/* reset the statement so it may be used again */
sqlite3_reset( stmt );
sqlite3_clear_bindings( stmt ); /* optional */
}
}
/* destroy and release the statement */
sqlite3_finalize( stmt );
a、sqlite3_prepare 创建一个预处理对象。
b、sqlite3_bind_xxx 绑定参数。
c、循环执行 sqlite3_step 获取数据。
d、sqlite3_column 从数据中取出每一段。
e、释放 sqlite3_finalize 。
1、插入
sqlite3_open -> sqlite3_prepare_v2 -> sqlite3_bind_xxx -> sqlite3_step -> sqlite3_reset -> sqlite3_finalize -> sqlite3_close
2、查询
sqlite3_open -> sqlite3_prepare_v2 -> sqlite3_step -> sqlite3_column_xxx -> sqlite3_finalize -> sqlite3_close
3、例子
略略略
常用命令
If you use an auto-increment field, you can easily write this to delete the oldest 100 records:
DELETE FROM mytable WHERE id IN (SELECT id FROM mytable ORDER BY id ASC LIMIT 100)
Or, if no such field is present, use ROWID
:
DELETE FROM mytable WHERE ROWID IN (SELECT ROWID FROM mytable ORDER BY ROWID ASC LIMIT 100)
Or, to leave only the latest 1000 records:
DELETE FROM mytable WHERE ROWID IN (SELECT ROWID FROM mytable ORDER BY ROWID DESC LIMIT -1 OFFSET 1000)
参考
An Introduction To The SQLite C/C++ Interface
C-language Interface Specification for SQLite