zoukankan      html  css  js  c++  java
  • SQLite函数详解之二

    sqlite3支持的数据类型:

    NULL、INTEGER、REAL、TEXT、BLOB
    但是,sqlite3也支持如下的数据类型
    smallint           16位整数
    integer             32位整数
    decimal(p,s)   p是精确值,s是小数位数
    float                  32位实数
    double             64位实数
    char(n)             n长度字符串,不能超过254
    varchar(n)        长度不固定最大字符串长度为n,n不超过4000
    graphic(n)        和 char(n) 一样,但是单位是两个字符double-bytes,n不超过127(中文字)
    vargraphic(n)  可变长度且最大长度为n

    date                  包含了年份、月份、日期
    time                  包含了小时、分钟、秒
    timestamp       包含了年、月、日、时、分、秒、千分之一秒

    sqlite3支持的函数

    【1】日期函数

    datetime() : 产生日期和时间
    date(): 产生日期
    time():产生时间
    strftime():对以上3个函数产生的日期和时间进行格式化

    用法实例:
    1、SELECT date('2011-9-9','+1 day','+1 year'); 结果是 2010-09-10
    2、SELECT datetime('now'); 当前日期和时间
    3、SELECT datetime('now', 'start of month'); 本月的第一天零点,也可以设置年和日的第一天
    4、SELECT datetime('now','+1 hour','-12 minute'); 当前时间加48分钟

    strftime()函数可以将YYYY-MM-DD HH:MM:SS格式的日期字符串转换为其它形式的字符串

    %d:天数,01-31
    %f :小数形式的秒,SS.SSS
    %H:小时
    %j  :某一天是该年的第几天,001-366
    %m:月份,00-12
    %M:分钟,00-59
    %s:从1970到现在的秒数
    %S:秒,00-59
    %w:星期,0-6,0是星期天
    %W:某天是该年的第几周,01-53
    %Y:年,YYYY
    %% 百分号

    应用举例:
    SELECT strftime('%Y.%m.%d %H:%M:%S','now','localtime');


    二、【算术函数】

    abs(X):返回绝对值
    max(X,Y[,...]):返回最大值
    min(X,Y,[,...]):返回最小值
    random(*):返回随机数
    round(X[,Y]): 四舍五入

    三、【字符串处理函数】

    length(x) :返回字符串字符个数
    lower(x) :大写转小写
    upper(x):小写转大写
    substr(x,y,Z):截取子串
    like(A,B):确定给定的字符串与指定的模式是否匹配

    四、【条件判断函数、集合函数、其它函数】

    typeof(x):返回数据的类型
    last_insert_rowid():返回最后插入的数据的ID

    ********************************************************************************************************************

    sqlite3提供了C函数接口来操作sqlite3数据库,其中有个关键数据结构 sqlite3 * 类型

    1、打开数据库
    int sqlite3_open(文件名,sqlite3 **);  - 文件名若不存在,则会自动创建
    返回SQLITE_OK表示操作正常,这些宏的定义在sqlite3.h文件中定义,看源代码会懂的更多

    2、关闭数据库
    int sqlite3_close(sqlite3 *);

    3、SQL语句操作
    int sqlite3_exec(sqlite3 *,const char *sql, sqlite3_callback,void *,char **errmsg);
    这就是执行一条sql语句的函数
    参数1:open函数得到的指针
    参数2:一条sql语句,以''结尾
    参数3:sqlite3_callback是回调,当这条语句执行后,sqlite3会调用你提供的这个函数,回调函数要查阅资料
    参数4:void *是自己提供的指针,可以传递任何指针到这里,这个参数最终会传到回调函数里面,如果不需要
    传到回调函数里面,则可以设置为NULL
    参数5:错误信息,当执行失败时,可以查阅这个指针,可以利用printf("%s ",errmsg)得到一串字符串信息,
    该信息表明出错的地方

    通常,sqlite3_callback和void *都设置为NULL,表示不需要回调,比如做insert、delete操作,就没有必要使用回调,而当使用select时,就要使用回调,因为sqlite3把数据查出来,得通过回调来说明查出什么数据


    回调函数的定义格式:
    typedef int (*sqlite3_callback)(void *,int,char **,char **);

    实例如下:

    1. //sqlite 每查到一条记录,就调用一次这个回调  
    2. int LoadMyInfo(void *para,int n_column,char **column_value,char **column_name)  
    3. {  
    4.     /*para: 在sqlite3里传入的void *参数,通过该参数可以传入一些特殊指针 
    5.      *如类指针、结构指针,然后在这里转换成对应的类型(这里是void *类型), 
    6.      *必须强制转换成自己的类型才可用,然后操作这些数据*/  
    7.        
    8.     //n_column: 该记录有多少个字段(列)  
    9.       
    10.     /*char **column_value 保存着查出来的数据,实际上是个1维数组,每一个元素都是 
    11.      *char *值,是一个字段内容(用字符串表示,以结尾)*/  
    12.        
    13.     //char **column_name 与 column_value 是对应的,表示这个字段的字段名称  
    14.       
    15.     //这里不是用para参数  
    16.       
    17.     printf("%=记录包含%d 个字段",n_column);  
    18.       
    19.     for(i=0;i<n_column;i++)  
    20.     {  
    21.         printf("字段名: %s ,字段值:%s ",column_name[i],column_value[i]);  
    22.     }  
    23.       
    24.     printf(" ");  
    25.       
    26.     return 0;  
    27. }  
    28.   
    29. int main(int , char **)  
    30. {  
    31.     sqlite3 *db;  
    32.     int result;  
    33.     char *errmsg = NULL;  
    34.     char sql[512];  
    35.       
    36.     result = sqlite3_open("My.db",&db);  
    37.     if(result != SQLITE_OK)  
    38.     {  
    39.         //数据库打开失败  
    40.         return -1;   
    41.     }  
    42.       
    43.     //创建数据表  
    44.     strcpy(sql,"CREATE TABLE test(ID INTEGER PRIMARY KEY,NAME VARCHAR(32));");  
    45.     result = sqlite3_exec(db,sql,NULL,NULL,errmsg);  
    46.     if(result != SQLITE_OK)  
    47.     {  
    48.         printf("创建表失败,错误:%s ",errmsg);  
    49.     }  
    50.       
    51.     //插入记录  
    52.     strcpy(sql,"INSERT INTO test VALUES(1,'OK');");  
    53.     result = sqlite3_exec(db,sql,0,0,errmsg);  
    54.     if(result != SQLITE_OK)  
    55.     {  
    56.         printf("插入记录失败,错误:%s ",errmsg);  
    57.     }  
    58.       
    59.     //查询数据库  
    60.     strcpy(sql,"SELECT * FROM test;");  
    61.     result = sqlite3_exec(db,sql,LoadMyInfo,NULL,errmsg);  
    62.       
    63.     sqlite3_close(db);  
    64.       
    65.     return 0;  
    66. }  


    以上是通过回调查询数据库,如果该函数在C++中,就要将其声明成static类型,因为C++
    成员函数隐藏了一个参数:this,C++调用类的成员函数的时候,隐含把类指针当函数的第
    一个参数传递进去,就与上面的sqlite回调函数参数不符

    除了使用回调来查询,还可以使用非回调的查询,通过sqlite3_get_table函数做到
    int sqlite3_get_table(sqlite3*,const char *sql,char ***resultp,int *nrow,int *ncolumn,char **errmsg);
    参数3:resultp 是一维数组,第一行是字段名称,跟着是每个字段的值
    参数4:查询共多少条记录
    参数5:查询共多少个字段

    操作实例如下:

    1. int main(int ,char **)  
    2. {  
    3.     sqlite3 *db;  
    4.     int result;  
    5.     char *errmsg = NULL;  
    6.       
    7.     char **dbResult;  
    8.     int nRow,nColumn;  
    9.     int i,j;  
    10.     int index;  
    11.       
    12.     char sql[512];  
    13.       
    14.     result = sqlite3_open("My.db",&db);  
    15.     if(result != SQLITE_OK)  
    16.     {  
    17.         return -1;  
    18.     }  
    19.       
    20.     result = sqlite3_get_table(db,sql,&dbResult,&nRow,&nColumn,&errmsg);  
    21.     //查询成功  
    22.     if(SQLITE_OK == result)   
    23.     {  
    24.         //dbResult第一行是字段名称,从nColumn索引开始时真正的数据  
    25.         index = nColumn;  
    26.         printf("查询到%d记录 ",nRow);  
    27.           
    28.         for(i=0;i<nRow;i++)  
    29.         {  
    30.             for(j=0;j<nColumn;j++)  
    31.             {  
    32.                 printf("字段名称:%s,字段值:%s ",dbResult[j],dbResult[index]);  
    33.                 index++;  
    34.             }  
    35.             printf(" ");  
    36.         }  
    37.     }  
    38.       
    39.     //释放char**查询结果  
    40.     sqlite3_free_table(dbResult);   
    41.       
    42.     sqlite3_close(db);  
    43.       
    44.     return 0;  
    45. }  


    上述使用的方法适用于大多数数据库需求,但是不能适用于二进制数据,操作二进制数据方法需要用到一个数据类型sqlite3_stmt *,该数据类型记录了一个"sql语句",这里的sql语句是解析后的,用sqlite自己标记记录的内部数据结构,并不是我们熟悉的sql语句

    数据插入到 sqlite3_stmt结构里可不能直接memcpy,也不能像std::string那样用+号,必须用sqlite提供的
    函数来插入。

    假设有创建一张表如下
    CREATE TABLE test2(ID INTEGER,file_content BLOB)

    首先声明 sqlite3_stmt *stat; 然后将一个sql语句解析到stat结构里去
    sqlite3_prepare(db,"INSERT INTO test2(ID,file_content) VALUES(10,?)",-1,&stat,0);
    这里sql语句中有个?号,在该函数里,?表示一个未定的值
    参数3:表示前面sql语句的长度,如果小于0,sqlite会自动计算它的长度
    参数4:sqlite3_stat指针的指针,解析后的sql语句就放在该结构里
    参数5:一般设为0

    返回值为SQLITE_OK且stat不为NULL,表示成功,当prepare成功后,开始查询数据
    int result = sqlite3_step(stat);
    该值返回SQLITE_ROW 表示成功

    可以循环执行sqlite3_step函数,一次step查询出一条记录,直到返回值不为SQLITE_ROW
    然后开始获取第一个字段:ID值,ID是个整数,使用如下操作
    int id = sqlite3_column_int(stat,0); //0表示第1字段
    下面获取file_content的值,因为file_content是二进制,因此需要得到它的指针,还有长度
    const void * pFileContent = sqlite3_column_blob(stat,1);
    int len = sqlite3_column_bytes(stat,1);
    把 pFileContent内容保存后,要释放sqlite3_stmt结构
    sqlite3_finalize(stat);

    如果需要重复使用 sqlite3_prepare解析好的sqlite3_stmt结构,使用 sqlite3_reset函数
    result = sqlite3_reset(stat);
    这样,stat结构又成为sqlite3_prepare完成时的状态

    sqlite 数据库事务处理

    如果需要同步删除很多数据,可以将它们做成一个统一的事务,通常sqlite3_exec就是一次事务,假设要删除1W条记录,sqlite就做了1W次,开始事务->删除数据->提交事务,这个操作很慢,我们可以将同类操作作成一个事物,如果操作错误,还可以回滚事务

    事务的操作没有特别的接口函数,只是普通的sql语句
    int result;
    result = sqlite3_exec(db,"begin transtraction",0,0,&zErrorMsg);
    result = sqlite3_exec(db,"commit transtraction",0,0,&zErrorMsg);
    result = sqlite3_exec(db,"rollback transtraction",0,0,&zErrorMsg);

     sqlite3 错误编码如下:

    1. #define SQLITE_OK           0   /* Successful result */  
    2. #define SQLITE_ERROR        1   /* SQL error or missing database */  
    3. #define SQLITE_INTERNAL     2   /* An internal logic error in SQLite */  
    4. #define SQLITE_PERM         3   /* Access permission denied */  
    5. #define SQLITE_ABORT        4   /* Callback routine requested an abort */  
    6. #define SQLITE_BUSY         5   /* The database file is locked */  
    7. #define SQLITE_LOCKED       6   /* A table in the database is locked */  
    8. #define SQLITE_NOMEM        7   /* A malloc() failed */  
    9. #define SQLITE_READONLY     8   /* Attempt to write a readonly database */  
    10. #define SQLITE_INTERRUPT    9   /* Operation terminated by sqlite_interrupt() */  
    11. #define SQLITE_IOERR       10   /* Some kind of disk I/O error occurred */  
    12. #define SQLITE_CORRUPT     11   /* The database disk image is malformed */  
    13. #define SQLITE_NOTFOUND    12   /* (Internal Only) Table or record not found */  
    14. #define SQLITE_FULL        13   /* Insertion failed because database is full */  
    15. #define SQLITE_CANTOPEN    14   /* Unable to open the database file */  
    16. #define SQLITE_PROTOCOL    15   /* Database lock protocol error */  
    17. #define SQLITE_EMPTY       16   /* (Internal Only) Database table is empty */  
    18. #define SQLITE_SCHEMA      17   /* The database schema changed */  
    19. #define SQLITE_TOOBIG      18   /* Too much data for one row of a table */  
    20. #define SQLITE_CONSTRAINT  19   /* Abort due to contraint violation */  
    21. #define SQLITE_MISMATCH    20   /* Data type mismatch */  
    22. #define SQLITE_MISUSE      21   /* Library used incorrectly */  
    23. #define SQLITE_NOLFS       22   /* Uses OS features not supported on host */  
    24. #define SQLITE_AUTH        23   /* Authorization denied */  
    25. #define SQLITE_ROW         100  /* sqlite_step() has another row ready */  
    26. #define SQLITE_DONE        101  /* sqlite_step() has finished executing */  

  • 相关阅读:
    [Java]lambda表达式
    [设计模式]访问者模式
    【Java】基本数据类型
    【JavaWeb】防止表单的重复提交
    [Java]异常在项目中的使用
    Java容器-个人整理1
    【MyBatis-Spring】Mybatis和并入Spring框架
    python 正则表达式模块——re 知识点小结
    关于使用python批量操作网络设备(交换机,路由器)的知识点小结
    GitHub 基础常用命令用法
  • 原文地址:https://www.cnblogs.com/zhangruilin/p/5769850.html
Copyright © 2011-2022 走看看