使用Sqlite的几个小技巧

 作者:youco

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 COLUMNRENAME TABLE还是可以支持的。其实这一点翻翻官方文档就知道,不过我刚开始用的时候还是被困扰了一下。


   关于sqlite3不支持的SQL特性, 可以参考官方文档


你可能感兴趣的:(使用Sqlite的几个小技巧)