Sqlite3作为一个轻量级的数据库,相信很多人(特别是做移动设备应用开发的人)都接触过,相关的资料文档也是一搜一大把。所以关于SQL语句和基本API方面的东西我不打算写了,只想写几个小tips,如有错误还请指出。
(本文的内容针对cppSQlite3, 它是对Sqlite的一个C++封装,可以从sqlite官网下载)
1. 在SQL语句中加入自定义函数
假设我在一张表里存储了中文名字和国家代码,另外有一个函数可以根据国家代码把中文名译为对应的语言。如果想直接用一条SQL语句来检索出翻译后的名字该怎么做呢?可以使用以下的方法来创建用户自定义的SQL函数:
int sqlite3_create_function(
sqlite3 *, //database handle
const char *zFunctionName, //自定义函数名
int nArg, //参数个数,如果为-1则可接受任意数量参数
int eTextRep, //传入参数编码形式
void* pApp, //传入参数指针,可以通过 sqlite3_user_data()方法获取
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
void (*xFinal)(sqlite3_context*)
);
eTextRep的可能取值如下:
#define SQLITE_UTF8 1
#define SQLITE_UTF16 2
#define SQLITE_UTF16BE 3
#define SQLITE_UTF16LE 4
#define SQLITE_ANY 5
后三个参数为函数指针。如果你定义的是一般函数,只需要设置 xFunc 参数,而把 xStep 和 xFinal 设为NULL。如果你定义的是聚合函数,则需要把xFunc设为NULL并设置 xStep 和 xFinal 参数。
这样的说明比较抽象,下面举一个完整的例子来实现前面所说的功能。
如果要在SQL语句中加入一个函数MyFunc,它接受两个参数,那么先定义函数
void my_func(sqlite3_context * ctx, int argc, sqlite3_value ** argv)
{
if ( argc != 2 )
return;
if( sqlite3_value_type( argv[ 0 ] ) != SQLITE_TEXT)
return;
if( sqlite3_value_type( argv[ 1 ] ) != SQLITE_TEXT)
return;
const char * name = (const char * )sqlite3_value_text( argv[ 0 ] );
const char * countryCode = (const char * )sqlite3_value_text( argv[ 1 ] );
//定义函数,略。执行结果放在char* 型的result里。
sqlite3_result_text(ctx, result, strlen(result), SQLITE_TRANSIENT);
}
再调用
sqlite3_create_function( hDB, "MyFunc", 2, SQLITE_ANY, NULL, my_func, NULL, NULL );
接下来就可以执行类似的SQL语句了
SELECT MyFunc(Name, CountryCode) FROM TableName1;
2. 主键值的插入
假设数据库A和数据库B中都包含同样结构的一张表Phone_table,例如
数据库A中的Phone_table
Id |
Name |
Phone |
999 |
Jane |
62612255 |
1000 |
Mary |
28001359 |
Id是主键,int64型,共有1000条记录。
数据库B中的Phone_table
Id |
Name |
Phone |
299 |
Tom |
67132214 |
300 |
Sherry |
70321506 |
含有300条记录。
现在想把数据库B中的数据插入到数据库A中,如果直接用
INSERT INTO A.Phone_table SELECT * FROM B.Phone_table;
一定会报主键冲突。解决的方法也有很多种,比如在B.Phone_table.Id上加上MAX(A.Phone.Id)之类的。但是我认为最方便的办法是用下面的语句:
INSERT INTO A.Phone_table SELECT NULL, Name, Phone FROM B.Phone_table;
对于主键值,在插入NULL的情况下,会自动进行填充。以上表为例,从B数据库中插入的记录Id会被自动编为1001~1300。
3. Sqlite3比标准SQL缺少的功能
Sqlite3是不支持通过ALTER TABLE来进行DROP COLUMN, ALTER COLUMN等操作的。如果想从表中删除或更改一列,只能先把整张表删除,再重新建表。不过,ADD COLUMN和RENAME TABLE还是可以支持的。其实这一点翻翻官方文档就知道,不过我刚开始用的时候还是被困扰了一下。
关于sqlite3不支持的SQL特性, 可以参考官方文档。