• SQLite3使用笔记(1)——查询


    1. 概述

    SQLite是一个嵌入式SQL数据库引擎。与大多数其他 SQL 数据库不同,SQLite 没有单独的服务器进程。SQLite 直接读写普通磁盘文件。具有多个表、索引、触发器和视图的完整SQL数据库包含在单个磁盘文件中。

    SQLite比MySQL还要轻量级,官方提供的程序包大约1MB。但是这么小的内容居然也是一个关系型数据库,所以SQLite也很适合作为入门数据库。其中,SQL最基础的功能就是查询了。

    2. 详论

    2.1. 打开/关闭数据库

    使用数据库的第一步当然是打开数据库了。对于C接口来说,通常的实现是提供一个打开的接口,得到一个句柄或者指针,然后通过这个句柄或者指针进行进一步操作,包括关闭数据库操作。SQLite正是这么设计的:

      int nRes = sqlite3_open("D:/test.db", &pDB);
      if (nRes != SQLITE_OK) {
        cout << "Open database fail: " << sqlite3_errmsg(pDB);
        return 1;
      }
    
    
      sqlite3_close(pDB);
    

    通过sqlite3_open()这个函数打开数据库文件,如果数据库.db文件不存在,则会创建这个文件文件。一旦创建成功,在程序结束时最好调用sqlite3_close()这个函数进行关闭,否则会内存泄漏。如果需要更加精细的打开数据库文件控制,最好使用sqlite3_open_v2()这个接口:

      int flags =
          SQLITE_OPEN_READWRITE | SQLITE_OPEN_NOMUTEX | SQLITE_OPEN_SHAREDCACHE;
      int nRes = sqlite3_open_v2("D:/test.db", &pDB, flags, nullptr);
    

    sqlite3_open_v2()提供了很多打开数据库文件时的配置,例如如果需要在数据库文件不存在时进行创建,可以再加上SQLITE_OPEN_CREATE。

    2.2. 数据查询

    如果在可视化管理工具(例如SQLite Expert)中,无论是查询、插入、修改或者删除操作,都是直接输入SQL语句,然后执行运行操作,就可以得到相应的结果。SQLite也有这样的接口sqlite3_exec(),例如我们查询一个表中所有的数据:

      char* cErrMsg;
      int res =
          sqlite3_exec(pDB, "select * from metadata;", ResultCallBack, 0, &cErrMsg);
    
      if (res != SQLITE_OK) {
        cout << "select fail: " << cErrMsg << endl;
        return false;
      }
    
      sqlite3_free(cErrMsg);
    

    sqlite3_exec()是一个回调函数,每查询到一行数据就调用一次:

    int ResultCallBack(void* NotUsed, int argc, char** argv,
                              char** azColName) {
      for (int i = 0; i < argc; i++) {
        cout << azColName[i] << " = " << (argv[i] ? argv[i] : "NULL") << ", ";
      }
      cout << endl;
    
      return 0;
    }
    

    如果需要进行更加细粒度的控制,那么一个合适的做法是使用statement(语句)。首先,我们将我们需要的sql语句编译成数据库引擎识别的字节码,这个步骤可以叫做prepare(准备):

      sqlite3_stmt* statement = nullptr;
      int ret = sqlite3_prepare_v2(pDB, sqlStr, -1, &statement, nullptr);
      if (ret != SQLITE_OK) {
        printf("prepare error ret : %d\n", ret);
        return 1;
      }
    

    接着,就是执行准备好的SQL语句:

      while (sqlite3_step(statement) == SQLITE_ROW) {	  	   
          //...
      }
    

    sqlite3_setp()每次查询一行记录,并且返回SQLITE_ROW;知道查询完成,就返回SQLIET_DONE。通过这种方式实现了一种类似迭代器的操作,循环遍历每个查询结果。

    最后,我们对每一行查询的结果进行解析:

      while (sqlite3_step(statement) == SQLITE_ROW) {
        cout << sqlite3_data_count(statement) << '\n';
        cout << sqlite3_column_text(statement, 0) << '\t'
             << sqlite3_column_text(statement, 1) << '\n';
      }
    

    sqlite3_column_X是一系列函数,可以直接获取每一行相应列的数据类型。例如获取整型就是sqlite3_column_int。

    另外,不要忘了关闭这个语句:

    sqlite3_finalize(statement);
    

    3. 参考

    1. SQLite3中核心C API
  • 相关阅读:
    剑指offer55. 平衡二叉树
    剑指offer52. 两个链表的第一个公共节点
    LC1043. Partition Array for Maximum Sum
    剑指offer40. Top K
    剑指offer39. 数组中出现次数超过一半的数字
    剑指offer36.将BST原地转换为双向循环链表
    判断大小端
    CentOS安装RabbitMQ 3.8.9
    Nginx 413 Request Too Large 错误
    NginxPC端和移动端区分
  • 原文地址:https://www.cnblogs.com/charlee44/p/16297929.html
Copyright © 2020-2023  润新知