IT评测·应用市场-qidao123.com技术社区

标题: 嵌入式数据库SQLite 3配置使用具体条记教程 [打印本页]

作者: 曹旭辉    时间: 2024-8-15 00:33
标题: 嵌入式数据库SQLite 3配置使用具体条记教程
0、凄惨教训

        随着管理开辟的项目体积越来越巨大,产品体系涉及的数据量也越来越多,而且陪同着项目不久就要交付给甲方了。如果项目的数据信息没有被妥善管理,后期装备的运行状态、操作状况等数据流信息不能被溯源,当出现了一些特殊不测时,就会导致对于故障信息不能迅速准确的追踪,甚至会被甩锅、推卸责任,白白当了冤大头。因此对于嵌入式项目中,其产品运行时的数据库建立非常有必要,且是迫在眉睫!!!
        现在常用的数据库体系有:MySQL、PostgreSQL、Oracle Database、Microsoft SQL Server、SQLite等。在嵌入式项目中,前面几个数据库显然是不符合的,而SQLite是一个轻量级的数据库管理体系,它包罗在一个C库中,提供了零配置、无服务器、事务性的SQL数据库引擎。以是SQLite的特点使其非常适合嵌入式体系、移动装备、小型项目大概作为应用步调的本地数据库使用。本文选用了嵌入式数据库SQLite3进行配置和讲解。
1、Sqlite3环境配置

(1)、下载安装SQLite库

根据目的体系平台,下载sqlite源码,或下载官方提供的已经编译好的库。本文目的平台是Windows11 64位平台,进入SQLite Download Page的主页,选择需要的库版本(Windows)。

下载的压缩包一共有如下所示的三个:
sqlite-dll-win-x64-3450300.zip
sqlite-dll-win-x86-3450300.zip
sqlite-tools-win-x64-3450300.zip

(2)、解压下载的文件

        本文中将对应的Sqlite库文件解压到了,C:\Program Files\sqlite路径下。

(3)、添加库路径到环境变量

        根据下图所示的步调,进入体系属性-->环境变量-->体系变量-->编辑环境变量,将路径加入到环境变量中。

(4)、检查数据库安装状态

        打开Windows的下令行,输入sqlite3,有类似如下的数据信息说明库安装乐成,后续只需在步调代码中,将库加入到工程代码中即可。

(5)、SQLiteStudio工具

        如果有可视化分析数据需求、保举使用下载:SQLiteStudio
https://sqlitestudio.pl/

2、SQLite3基础

        SQL(Structured Query Language)是一种结构化查询语言,SQL 是一种专门用来与数据库通讯的语言。
        不同的数据库管理体系在实在践过程中都对 SOL 规范作了某些改编和扩充。故不同数据库管理体系之间的 SOL语言不能完全相互通用。
        以下是SQLite的一些关键特点:

        有个重要的点值得注意,SQLite 是不区分巨细写的,但也有一些下令是巨细写敏感的,比如 GLOB 和 glob 在 SQLite 的语句中有不同的寄义。一般数据接纳固定的静态数据类型,而 SOLite 接纳的是动态数据类型,会根据存入值自动判断。
SQLite 存储类:SOLite 具有以下五种根本数据类型
(1)integer:带符号的整型(最多64位)。
(2)real:8字节体现的浮点类型。
(3)text:字符类型,支持多种编码(如 UTF-8、UTF-16),巨细无穷制。
(4)blob:任意类型的数据,巨细无穷制。 BLOB(binary large obiect)二进制大对象,使用二进制生存数据。
(5)null:体现空值
SQLite 亲和类型(Affinity)及类型名称
下表列出了当创建 SQLite3 表时可使用的各种数据类型名称,同时也表现了相应的亲和类型
数据类型
亲和类型
     

  • INT
  • INTEGER
  • TINYINT
  • SMALLINT
  • MEDIUMINT
  • BIGINT
  • UNSIGNED BIG INT
  • INT2
  • INT8
INTEGER
     

  • CHARACTER(20)
  • VARCHAR(255)
  • VARYING CHARACTER(255)
  • NCHAR(55)
  • NATIVE CHARACTER(70)
  • NVARCHAR(100)
  • TEXT
  • CLOB
TEXT
     

  • BLOB
  • 未指定类型
BLOB
     

  • REAL
  • DOUBLE
  • DOUBLE PRECISION
  • FLOAT
REAL
     

  • NUMERIC
  • DECIMAL(10,5)
  • BOOLEAN
  • DATE
  • DATETIME
NUMERIC
SQLite 语句:所有的 SQLite 语句可以以任何关键字开始,如 SELECT、INSERT、UPDATE、DELETE、ALTER、DROP 等,所有的语句以分号 ; 结束。
3、SQLite3根本语法

(1)、创建数据库

  1. //打开数据库,如不存在则会创建数据库
  2. int ret = sqlite3_open("project_data.db", &db);
  3. if( ret )
  4. {
  5.     fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
  6.     exit(-1);
  7. }
  8. fprintf(stderr, "Opened database successfully\n");
复制代码
(2)、创建表

  1. //CREATE TABLE 告诉数据库系统创建一个新表的关键字。CREATE TABLE 语句后跟着表的唯一的名称或标识。
  2. CREATE TABLE database_name.table_name(
  3.    column1 datatype  PRIMARY KEY(one or more columns),
  4.    column2 datatype,
  5.    column3 datatype,
  6.    .....
  7.    columnN datatype,
  8. );
  9. char table_name[200] = {0};
  10. char *err_msg = NULL;
  11. snprintf(table_name, sizeof(table_name), "create table if not exists camera(time_stamp integer primary key, action text, x integer, y integer, z integer, vx integer, vy integer, vz integer, time integer);");
  12. int ret = sqlite3_exec(db, table_name, NULL, NULL, &err_msg);
  13. if(ret){
  14.     fprintf(stderr, "create table err:%s\n", err_msg);
  15.     return -1;
  16. }
  17. fprintf(stderr, "create table successfully\n");
复制代码
(3)、删除表

  1. //SQLite 的 DROP TABLE 语句用来删除表定义及其所有相关数据、索引、触发器、约束和该表的权限规范。
  2. //DROP TABLE 语句的基本语法如下。
  3. DROP TABLE database_name.table_name;
  4. char table_name[200] = {0};
  5. char *err_msg = NULL;
  6. snprintf(table_name, sizeof(table_name), "DROP TABLE database_name.table_name;");
  7. int ret = sqlite3_exec(db, table_name, NULL, NULL, &err_msg);
  8. if(ret){
  9.     fprintf(stderr, "delete table err:%s\n", err_msg);
  10.     return -1;
  11. }
  12. fprintf(stderr, "delete table successfully\n");
复制代码
(4)、插入数据

  1. INSERT INTO 语句有两种基本语法,如下所示:
  2. INSERT INTO TABLE_NAME [(column1, column2, column3,...columnN)]  VALUES (value1, value2, value3,...valueN);//在这里,column1, column2,...columnN 是要插入数据的表中的列的名称
  3. INSERT INTO TABLE_NAME VALUES (value1,value2,value3,...valueN);
  4. //确保值的顺序与列在表中的顺序一致。
  5. char table_value[200] = {0};
  6. int ret = 0;
  7. char *err_msg = NULL;
  8. snprintf(table_value, sizeof(table_value),"insert into camera values(%lld, '%c', %d, %d, %d, %d, %d, %d, %d);", get_current_timestamp_ms(), action, x, y, z, vx, vy, vz, time);
  9. ret = sqlite3_exec(db, table_value, NULL, NULL, &err_msg);
  10. if(ret)
  11. {
  12.     fprintf(stderr, "insert value to table err:%s\n", err_msg);
  13.     return -1;
  14. }
  15. fprintf(stderr, "insert value to table successfully\n");
复制代码
(5)、查询数据

  1. //SQLite 的 SELECT 语句用于从 SQLite 数据库表中获取数据,以结果表的形式返回数据。这些结果表也被称为结果集。
  2. //SQLite 的 SELECT 语句的基本语法如下:
  3. SELECT column1, column2, columnN FROM table_name;//在这里,column1, column2...是表的字段,他们的值即是您要获取的。
  4. SELECT * FROM table_name;    //获取所有可用的字段
  5. char *err_msg = NULL;
  6. sprintf(sql, "select * from table_value;");
  7. ret = sqlite3_exec(db, sql, NULL, NULL, &err_msg);   //执行 SQL 命令的快捷方式
  8. if(ret)
  9. {
  10.     fprintf(stderr, "Can't select sqlite value: %s\n", sqlite3_errmsg(db));
  11.     return -1;
  12. }
复制代码
(6)、删除数据

  1. //SQLite 的 DELETE 查询用于删除表中已有的记录。可以使用带有 WHERE 子句的 DELETE 查询来删除选定行,否则所有的记录都会被删除。
  2. //带有 WHERE 子句的 DELETE 查询的基本语法如下:
  3. DELETE FROM table_name
  4. WHERE [condition];
  5. //可以使用 AND 或 OR 运算符来结合 N 个数量的条件。
  6. char *err_msg = NULL;
  7. sprintf(sql, "DELETE FROM camera WHERE time_stamp = 123456789;");
  8. ret = sqlite3_exec(db, sql, NULL, NULL, &err_msg);   //执行 SQL 命令的快捷方式
  9. if(ret)
  10. {
  11.     fprintf(stderr, "Can't DELETE sqlite data: %s\n", sqlite3_errmsg(db));
  12.     return -1;
  13. }
复制代码
(7)、修改数据

  1. //SQLite 的 UPDATE 查询用于修改表中已有的记录。可以使用带有 WHERE 子句的 UPDATE 查询来更新选定行,否则所有的行都会被更新。
  2. //带有 WHERE 子句的 UPDATE 查询的基本语法如下:
  3. UPDATE table_name
  4. SET column1 = value1, column2 = value2...., columnN = valueN
  5. WHERE [condition];
  6. char *err_msg = NULL;
  7. sprintf(sql, "UPDATE camera SET action = 't' WHERE time_stamp = 123456789;");
  8. ret = sqlite3_exec(db, sql, NULL, NULL, &err_msg);   //执行 SQL 命令的快捷方式
  9. if(ret)
  10. {
  11.     fprintf(stderr, "Can't DELETE sqlite data: %s\n", sqlite3_errmsg(db));
  12.     return -1;
  13. }
复制代码
4、SQLite3代码

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <time.h>
  5. #include <sqlite3.h>
  6. int database_init();
  7. int write_motor_info_to_database(sqlite3 *db, int motor_id, double target_pos, double real_pos, double real_speed, double real_current);
  8. int write_camera_info_to_database(sqlite3 *db, char action, int x, int y, int z, int vx, int vy, int vz, int time);
  9. long long get_current_timestamp_ms(void);
  10. int main(void)
  11. {
  12.     printf("sqlite3 database test!\n");   
  13.     database_init();
  14.     return 0;
  15. }
  16. /**
  17.   * @brief  数据库初始化
  18.   * @param  NONE
  19.   * @retval 成功返回0, 失败返回-1
  20.   */
  21. int database_init(void)  
  22. {
  23.     int ret = -1;
  24.     sqlite3 *db;
  25.     char *err_msg = NULL;
  26.     char database_name[128] = {0};
  27.     //获取当前时间
  28.     struct tm t;
  29.     time_t now;
  30.     time(&now);
  31.     localtime_s(&t, &now);
  32.     snprintf(database_name, sizeof(database_name),"%02d%02d%02d.db", t.tm_year + 1900, t.tm_mon + 1, t.tm_mday);
  33.     printf("date:%s\n", database_name);
  34.    //打开数据库
  35.     ret = sqlite3_open(database_name, &db);
  36.     if( ret )
  37.     {
  38.         fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
  39.         return -1;
  40.     }
  41.     fprintf(stderr, "Opened database successfully\n");
  42.     char table_name[200] = {0};
  43.     //时间戳 目标位置 实际位置 实际速度 实际电流
  44.     //create table if not exists motor0 (time_stamp integer primary key, target_pos real, real_pos real, real_speed real, real_current, real);
  45.     for(int motor_id = 0; motor_id < 6; motor_id++)
  46.     {
  47.         snprintf(table_name, sizeof(table_name),"create table if not exists motor%d (time_stamp integer primary key, target_pos real, real_pos real, real_speed real, real_current real);", motor_id);
  48.         ret = sqlite3_exec(db, table_name, NULL, NULL, &err_msg);
  49.         if(ret)
  50.         {
  51.             fprintf(stderr, "create table err:%s\n", err_msg);
  52.             return -1;
  53.         }
  54.         fprintf(stderr, "create table successfully\n");
  55.     }
  56.     memset(table_name, 0, sizeof(table_name));
  57.     snprintf(table_name, sizeof(table_name), "create table if not exists camera(time_stamp integer primary key, action text, x integer, y integer, z integer, vx integer, vy integer, vz integer, time integer);");
  58.     ret = sqlite3_exec(db, table_name, NULL, NULL, &err_msg);
  59.     if(ret)
  60.     {
  61.         fprintf(stderr, "create table err:%s\n", err_msg);
  62.         return -1;
  63.     }
  64.     fprintf(stderr, "create table successfully\n");
  65.     write_motor_info_to_database(db, 0, 90.0, 87.2, 5.0, 0.85);
  66.     write_motor_info_to_database(db, 1, 90.0, 87.2, 5.0, 0.85);
  67.     write_motor_info_to_database(db, 2, 90.0, 87.2, 5.0, 0.85);
  68.     write_motor_info_to_database(db, 3, 90.0, 87.2, 5.0, 0.85);
  69.     write_motor_info_to_database(db, 4, 90.0, 87.2, 5.0, 0.85);
  70.     write_motor_info_to_database(db, 5, 90.0, 87.2, 5.0, 0.85);
  71.     write_camera_info_to_database(db, 't', 100,200,150,160,130,110,1000);
  72.    
  73.     return 0;
  74. }
  75. /**
  76.   * @brief  写入电机数据到数据库中
  77.   * @param  db:数据库文件描述符
  78.   * @param  target_pos:目标位置
  79.   * @param  real_pos:实际位置
  80.   * @param  real_speed:实际速度
  81.   * @param  real_current:实际电流
  82.   * @retval 写入成功返回0,失败-1
  83.   */
  84. int write_motor_info_to_database(sqlite3 *db, int motor_id, double target_pos, double real_pos, double real_speed, double real_current)
  85. {
  86.     char table_value[200] = {0};
  87.     int ret = 0;
  88.     char *err_msg = NULL;
  89.     //insert into motor0 values(1798345, 90.0, 88.66, 45.1, 0.97);
  90.     snprintf(table_value, sizeof(table_value),"insert into motor%d values(%lld, %.2f, %.2f, %.2f, %.2f);", motor_id, get_current_timestamp_ms(), target_pos, real_pos, real_speed, real_current);
  91.     ret = sqlite3_exec(db, table_value, NULL, NULL, &err_msg);
  92.     if(ret)
  93.     {
  94.         fprintf(stderr, "insert value to table err:%s\n", err_msg);
  95.         return -1;
  96.     }
  97.     fprintf(stderr, "insert value to table successfully\n");
  98.     return 0;
  99. }
  100. /**
  101.   * @brief  写入相机数据到数据库中
  102.   * @param  db:数据库文件描述符
  103.   * @param  action:动作
  104.   * @param  x:
  105.   * @param  y:
  106.   * @param  z:
  107.   * @param  vx:
  108.   * @param  vy:
  109.   * @param  vz:
  110.   * @retval 写入成功返回0,失败-1
  111.   */
  112. int write_camera_info_to_database(sqlite3 *db, char action, int x, int y, int z, int vx, int vy, int vz, int time)
  113. {
  114.     char table_value[200] = {0};
  115.     int ret = 0;
  116.     char *err_msg = NULL;
  117.     //insert into motor0 values(1798345, 90.0, 88.66, 45.1, 0.97);
  118.     snprintf(table_value, sizeof(table_value),"insert into camera values(%lld, '%c', %d, %d, %d, %d, %d, %d, %d);", get_current_timestamp_ms(), action, x, y, z, vx, vy, vz, time);
  119.     ret = sqlite3_exec(db, table_value, NULL, NULL, &err_msg);
  120.     if(ret)
  121.     {
  122.         fprintf(stderr, "insert value to table err:%s\n", err_msg);
  123.         return -1;
  124.     }
  125.     fprintf(stderr, "insert value to table successfully\n");
  126.     return 0;
  127. }
  128. /**
  129.   * @brief  获取毫秒级时间戳
  130.   * @param  NONE
  131.   * @retval 成功返回时间戳值,失败返回-1
  132.   */
  133. long long get_current_timestamp_ms(void)
  134. {
  135. #if defined(_WIN32) || defined(_WIN64)
  136.     struct _timeb timebuffer;
  137.     _ftime64_s(&timebuffer);
  138.     return (long long)timebuffer.time * 1000 + timebuffer.millitm;
  139. #elif defined(__unix__) || defined(__unix) || defined(unix)
  140.     struct timeval tv;
  141.     gettimeofday(&tv, NULL);
  142.     return (long long)tv.tv_sec * 1000 + tv.tv_usec / 1000;
  143. #endif
  144. }
复制代码
参考代码运行效果

使用可视化工具SQLiteStudio,对SQLite3数据库进行查看。



免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 IT评测·应用市场-qidao123.com技术社区 (https://dis.qidao123.com/) Powered by Discuz! X3.4