链接sqlite

一.sqlite库函数

1.sqlite3_open()函数

语法:*sqlite3_open(const char *filename, sqlite3 *ppDb)

作用:该例程打开一个指向 SQLite 数据库文件的连接,返回一个用于其他 SQLite 程序的数据库连接对象。

参数1:如果 filename 参数是 NULL或":memory:",那么 sqlite3_open() 将会在 RAM 中创建一个内存数据库,这只会在 session 的有效时间内持续。如果文件名 filename 不为 NULL,而是你创建的数据库文件名,那么 sqlite3_open() 将使用这个参数值尝试打开对应数据库文件。如果该名称的文件不存在,sqlite3_open() 将创建一个新的命名为该名称的数据库文件并打开。

参数2:sqlite3_open() 函数的第二个参数是一个指向 SQLite 数据库连接的指针。如果 sqlite3_open() 调用成功,该指针将指向新创建的数据库连接,您可以使用该指针执行其他 SQLite 操作,如执行 SQL 查询、管理数据库事务等。

返回值:sqlite3_open() 函数的返回值是一个整数,用于指示函数调用的结果。以下是可能的返回值:

  • SQLITE_OK:函数调用成功,已打开指定的数据库连接。
  • SQLITE_ERROR:发生了错误,无法打开数据库连接。例如,文件名无效或无法访问文件系统。
  • SQLITE_CANTOPEN:无法打开数据库文件。这可能是因为磁盘已满、权限不足或数据库文件损坏等原因导致的。
  • SQLITE_MISUSE:发生了程序错误,例如传递给函数的参数无效或在多线程环境中不正确地使用库函数。
  • 其他错误码:SQLite 库定义了许多其他可能的错误代码,每个代码表示一个特定类型的错误。

通常来说,如果您调用 sqlite3_open() 并且它返回 SQLITE_OK,这个你作为0理解,其他错误代表返回值为1,只是不同类型的1代表的错误不同而已,则可以开始使用通过该函数创建的数据库连接进行其他 SQLite 操作,否则需要检查返回值并根据具体情况采取必要的措施。

2. sqlite3_errmsg()函数

语法:const char *sqlite3_errmsg(sqlite3*);

参数:参数是一个 sqlite3 类型的指针,该指针代表与 SQLite 数据库关联的连接。

返回值:它返回一个指向包含最近一次执行 SQLite API 函数时发生的错误消息的静态字符串的指针。

3. sqlite3_close()函数

语法:sqlite3_close(sqlite3*)

作用:关闭之前调用 sqlite3_open() 打开的数据库连接

参数:一个 sqlite3 类型的指针

4. sqlite3_exec()函数

sqlite3_exec函数是SQLite库中的一个高级封装函数,用于执行SQL语句并返回执行结果。

函数原型:

int sqlite3_exec(
  sqlite3*,                                  // 数据库连接对象
  const char *sql,                           // 要执行的SQL语句
  int (*callback)(void*,int,char**,char**),  // 回调函数指针
  void *,                                    // 回调函数参数
  char **errmsg                              // 错误信息输出缓冲区
);

参数说明:

  • sqlite3*:已经打开的数据库连接对象;
  • const char *sql:要执行的SQL语句,可以是一条或多条SQL语句,语句之间用分号隔开;
  • int (*callback)(void*,int,char**,char**):回调函数指针,当SQL语句执行完毕后会调用该函数,该函数可以用于处理查询结果或者操作完成的回调;
  • void*:回调函数所需的参数;
  • char **errmsg:如果执行过程中发生错误,将会把错误信息存到该变量所指向的内存空间中。(注意,这里是一个二级指针)

函数返回值为整数类型,表示执行结果。如果执行成功,则返回 SQLITE_OK(0); 如果执行失败,则返回其他的错误码,例如 SQLITE_ERROR(-1) 等。

注意事项:

  1. 在使用sqlite3_exec函数时,需要特别注意SQL注入问题,应该避免直接在SQL语句中拼接用户输入的字符串,而应该采用参数绑定的方式。
  2. 在使用回调函数时,需要根据具体情况做好内存管理,避免内存泄漏等问题。

5.连接测试代码

#include <stdio.h>
#include <sqlite3.h>

int main()
{
   sqlite3 *db;
   char *zErrMsg = 0;
   int rc;

   rc = sqlite3_open("test.db", &db);

   if( rc ){
      fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
      exit(0);
   }else{
      fprintf(stderr, "Opened database successfully\n");
   }
   sqlite3_close(db);
}

此代码仅完成测试功能,没有实现其他功能。

二.链接数据库

1.下载sqlite3.h文件

下载链接在我上一篇博客里面有,可以查看上一篇博客sqlite基础

下载后记得解压到和你准备链接的数据库.db文件同一目录下。

2.链接

如果此时你运行测试文件,结果绝对报错,因为大多数windows下的编译软件带的库中都没有sqlite3.h库文件,此时你需要进行链接操作生成可执行文件。

具体怎么链接,每个编译软件不同,这里以CLion为例,进行演示。如果你的软件是DevC++,链接操作可以参考这篇博客Windows下链接。

操作步骤:

  • 1.下载好的sqlite3.h文件放在你准备链接的数据库文件同一目录下
  • 2.打开CLion,新建项目,工作目录选择你刚刚存放的位置
  • 3.编写CMake文件,代码在下面,复制粘贴即可,自动保存
  • 4.在main.c文件里写测试代码,编译运行

CMake代码:

cmake_minimum_required(VERSION 3.25)
project(db_work C)

set(CMAKE_C_STANDARD 11)
add_compile_options(-l sqlite3)
add_executable(db_work main.c sqlite3.c)

现在看不懂也没关系,后面会有一篇博客专门介绍makefile的,到时详细解释。

三.C语言实现sqlite操作

1.提前看

首先我们通过命令窗口,直到数据库文件原来就存在的信息,确保后面增加的信息是通过C语言操作实现的。

如果你不知道具体怎么操作,可以看上一篇博客:sqlite基础

我的当前数据库信息:

TvrR.jpg

我们现在演示的数据库里面有两个表COMPANY、student,其中COMPANY是一个空表,还没有插入信息;student表中仅有一条Alice的信息。

2.回调函数

在进行C语言实现sqlite操作之前,我们首先得理解一个概念,回调函数。回调函数是一种常见的编程技术,用于在异步程序中处理结果或事件。当执行某个操作时,通常需要等待该操作完成后才能继续执行下一步。在这种情况下,可以将回调函数传递给该操作,以便在操作完成时自动调用该函数。

是不是你还一头雾水,我们先了解程序执行两种方式,同步执行和异步执行。同步执行没什么好说的,即程序从上到下一行一行的顺序执行,但是如果某个进程有许多线程,又必须等某一线程执行,主线程才能继续进行时,如果是同步方式就要一直等待这个需要线程执行完,很容易时间长造成阻塞。这里我们就用了异步执行的方式,异步方式是指在程序运行过程中,某个操作需要花费一定的时间才能完成,而在等待这个操作完成之前,程序会继续执行后面的代码。当这个操作完成后,程序会自动调用相应的回调函数来处理结果。

现在应该明白回调函数的作用了吧,再继续理解,它既然是处理某个线程或操作的处理结果,怎么处理,是不是要定义一个函数来对结果进行处理,所以回调函数是一种在编程中常见的技术,它允许您将一个函数作为参数传递给另一个函数,以便在需要时执行该函数。

他的存在形式是什么呢,其实回调函数严格来说就是一个普通函数,就是处理某个操作结果的函数,它自己可以作为一个参数被操作函数调用而已。举个例子好理解:

#include <stdio.h>

// 回调函数类型定义
typedef void (*Callback)(int);

// 执行计算任务的函数
void calculate(int a, int b, Callback callback) {
    int result = a + b;
    // 调用回调函数,将结果传递给它
    callback(result);
}

// 回调函数的实现
void printResult(int result) {
    printf("The result is: %d\n", result);
}

int main() {
    // 调用 calculate 函数并传入回调函数
    calculate(1, 2, printResult);
    return 0;
}

这里我们又一个calculate函数,假设进程程序特别长,在进行calculate操作之后还有其他操作,就可以使用回调函数的编程技术,即本例中把回调函数printResult作为一个参数可以通过calculate引入,这样不需要等他计算结果出来主线程就可以进行后面的操作,等calculate函数把结果计算出来自己调用printResult来打印输出。

有的人说,我为什么要通过函数指针导入,在一个函数内部本身就可以调用另一个函数嘛,这样确实可以,但这样就变成了同步执行方式,它必须等a+b计算结果出来后才会执行printResult函数,如果a+b计算结果没出来,程序就一直卡在这里。

3.函数指针

知道回调函数之后,你就知道回调函数可以作为参数导入,那直接整个函数作为参数导入吗,它其实是一个函数指针来代替引入。

函数指针是什么,顾名思义,就是一个指向函数的指针,只不过他和平时指针的定义方式不同而已。例如void (*Callback)(int)这段代码的意思就是定义了一个回调函数类型 Callback,它表示一个以整型参数为输入、无返回值的函数指针类型。(左边返回值,右边输入)

那么typedef void (*Callback)(int) 这行代码的作用,其实是将 void (*Callback)(int) 取一个别名 Callback,使其可以被当成一个新的数据类型来使用。这样,在程序中可以直接声明 Callback 类型的变量,而不需要再写一长串复杂的函数指针声明。

比如上面例子中写成Callback callback,而不是写成void (*Callback)(int) callback

4.C语言创建表

源代码:

#include <stdio.h>
#include <stdlib.h>
#include "sqlite3.h"

//回调函数
static int callback(void *NotUsed, int argc, char **argv, char **azColName){
    int i;
    for(i=0; i<argc; i++){
        printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
    }
    printf("\n");
    return 0;
}

int main(int argc, char* argv[])
{
    sqlite3 *db;
    char *zErrMsg = 0;
    int  rc;
    char *sql;

    /*打开数据库*/
    rc = sqlite3_open("D:\\softwore work\\db work\\text.db", &db);
    if( rc ){
        fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
        exit(0);
    }else{
        fprintf(stdout, "Opened database successfully\n");
    }

    /* 创建表 */
    sql = "CREATE TABLE friend("  \
         "id INT PRIMARY KEY     NOT NULL," \
         "name           TEXT    NOT NULL," \
         "age            INT     NOT NULL," \
         "address        CHAR(50)," \
         "salary         REAL );";

    /* Execute SQL statement */
    rc = sqlite3_exec(db, sql, callback, 0, &zErrMsg);      //执行上面的sql语句
    if( rc != SQLITE_OK ){
        fprintf(stderr, "SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);           //释放内存函数,释放zErrMsg对应的内存空间
    }else{
        fprintf(stdout, "Table created successfully\n");
    }
    sqlite3_close(db);
    return 0;
}

这里面你理解上面知识点就好理解了,补充两点:

  • 反斜杠 “” 字符在许多编程语言中,包括 C 和其派生语言如 C++ 中用于指示一个语句延续到下一行。这被称为行继续字符。每行末尾的反斜杠用于连接(合并)多行字符串以形成单个字符串。这样可以通过将长行分成更小的块来使代码更易于阅读。如果没有反斜杠,则 SQL 语句会被视为多个独立的字符串,在执行代码时会导致语法错误。

  • 回调函数:本例的回调函数,通常用于 SQLite 数据库操作中的查询操作。

    它的参数包括:

    1. void *NotUsed:这是一个不使用的指针,通常可以忽略。
    2. int argc:这是一个整数,表示查询结果集的列数。
    3. char **argv:这是一个字符数组指针,它包含每个查询结果的值。每个元素都是一个字符串,存储了对应列的值。
    4. char **azColName:这是一个字符数组指针,它包含每个查询结果的列名。每个元素都是一个字符串,存储了对应列的名称。

    在这个回调函数中,它遍历了所有的查询结果,并打印输出了每个结果的列名和对应的值。最后返回0表示操作成功完成。这个回调函数常用于 SQLite 的查询操作中,在执行 select 语句时,SQLite 将结果逐行传递给该回调函数处理。(进行其他操作时,程序执行会很快,一般不会使用到回调函数)

5.演示结果

jpg

利用命令端口,可以看到在此基础上,我们成功建立一个friend的表。

四.其他操作

是不是理解上面的知识了,理解上面的知识后你应该就知道怎么使用C语言实现sqlite的其他操做了。

#include <stdio.h>
#include <stdlib.h>
#include <sqlite3.h>

static int callback(void *NotUsed, int argc, char **argv, char **azColName){
   int i;
   for(i=0; i<argc; i++){
      printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
   }
   printf("\n");
   return 0;
}

int main(int argc, char* argv[])
{
   sqlite3 *db;
   char *zErrMsg = 0;
   int rc;
   char *sql;

   /* Open database */
   rc = sqlite3_open("test.db", &db);
   if( rc ){
      fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
      exit(0);
   }else{
      fprintf(stderr, "Opened database successfully\n");
   }

   /* Create SQL statement */
   sql = "INSERT INTO friend "  \
         "VALUES (1, 'Paul', 32, 'California', 20000.00 ); " \
         "VALUES (2, 'Allen', 25, 'Texas', 15000.00 ); "     \
         "VALUES (3, 'Teddy', 23, 'Norway', 20000.00 );" \
         "VALUES (4, 'Mark', 25, 'Rich-Mond ', 65000.00 );";

   /* Execute SQL statement */
   rc = sqlite3_exec(db, sql, callback, 0, &zErrMsg);
   if( rc != SQLITE_OK ){
      fprintf(stderr, "SQL error: %s\n", zErrMsg);
      sqlite3_free(zErrMsg);
   }else{
      fprintf(stdout, "Records created successfully\n");
   }
   sqlite3_close(db);
   return 0;
}

例如本例修改后就完成了INSERT语句的操作。

五.Python sqlite3 模块 API

  1. connect(database[, timeout, isolation_level, detect_types, factory, cached_statements])

    打开数据库连接,并返回一个连接对象。其中:

    • database:要连接的数据库文件名。
    • timeout:超时时间,默认为 5.0 秒。
    • isolation_level:事务隔离级别,默认为 None
    • detect_types:是否自动检测数据类型,默认为 0(不检测)。
    • factory:用于创建游标对象的类。默认为 None,表示使用内置的游标类。
    • cached_statements:是否缓存 SQL 语句,默认为 100
  2. Cursor()

    创建一个游标对象,用于执行 SQL 命令并管理结果集。

  3. execute(sql[, parameters])

    执行 SQL 命令,并将参数传递给 SQL 命令中的占位符。其中:

    • sql:要执行的 SQL 命令。
    • parameters:可选参数,用于替换 SQL 命令中的占位符。
  4. fetchone()

    获取查询结果集中的下一行数据。

  5. fetchmany([size])

    获取查询结果集中的多行数据,最多返回 size 行。如果未指定 size,则默认为 Cursor.arraysize

  6. fetchall()

    获取查询结果集中的所有行数据。

  7. commit()

    提交当前事务。

  8. rollback()

    回滚当前事务。

  9. close()

    关闭游标对象和数据库连接。

在python中链接数据库并实现创建表的操作:

import sqlite3

conn = sqlite3.connect('D:\\softwore work\\db work\\text.db')
print ("数据库打开成功")
c = conn.cursor()
c.execute('''CREATE TABLE classmate
       (ID INT PRIMARY KEY     NOT NULL,
       NAME           TEXT    NOT NULL,
       AGE            INT     NOT NULL,
       ADDRESS        CHAR(50),
       SALARY         REAL);''')
print ("数据表创建成功")
conn.commit()
conn.close()

六.情况说明

懂了之后,其实操作并不难,python链接相对来说比C语言简单。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/15762.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

8个免费的PNG素材网站推荐

很多设计小白都不知道什么是PNG。事实上&#xff0c;PNG是一种支持透明度的图像格式。当你想在设计中将图像与背景或文本混合时&#xff0c;它就会派上用场。 如果你没有时间为你正在处理的设计创建透明的PNG图像&#xff0c;你也可以使用我收集的PNG素材网站&#xff0c;以便…

Mysql-SQL优化

SQL优化 插入数据优化1&#xff09;批量插入数据2&#xff09;手动控制事务3&#xff09;主键顺序插入大批量插入数据 主键优化order by优化group by优化limit优化count优化update优化小结 插入数据优化 插入数据优化主要是对于insert进行批量插入时优化&#xff0c;下面我们就…

d3.js学习笔记②搭建服务器(含报错解决)

强烈建议自己搭建一个服务器&#xff0c;否则在后续往js里导入本地数据&#xff08;比如csv、json文件等&#xff09;的时候会报错。我用的是Apache服务器&#xff0c;下载、安装过程参考这篇文章&#xff1a;Apache安装配置 在浏览器输入http://localhost/或者http://127.0.0…

excel实战小测第四

【项目背景】 本项目为某招聘网站部分招聘信息&#xff0c;要求对“数据分析师”岗位进行招聘需求分析&#xff0c;通过对城市、行业、学历要求、薪资待遇等不同方向进行相关性分析&#xff0c;加深对数据分析行业的了解。 结合企业真实招聘信息&#xff0c;可以帮助有意转向数…

一文看懂数据分析必备计算功能—内存计算

各位数据的朋友&#xff0c;大家好&#xff0c;我是老周道数据&#xff0c;和你一起&#xff0c;用常人思维数据分析&#xff0c;通过数据讲故事。 接下来&#xff0c;我们准备讲一系列的奥威BI软件的内存计算在各种分析场景中的应用。在正式开讲之前&#xff0c;我先简单说一下…

嵌入式设备显示屏相关概念汇总

嵌入式设备常用的显示屏接口 LCD 接口&#xff1a;是一种常见的数字电路接口&#xff0c;支持多种显示器件&#xff0c;如字符型液晶显示器和点阵型液晶显示器等。 VGA 接口&#xff1a;是一种视频接口标准&#xff0c;用于连接显示器和计算机。该接口提供模拟 RGB 信号&#…

快速多关键字统计

实例需求&#xff1a;在每个章节中统计关键字&#xff08;“√”, “”, “〇”, “空缺”&#xff09;的个数&#xff0c;B列中的章节编号作为章节划分的标识&#xff0c;例如1.1.1 ~ 1.1.5为第1.1章节&#xff0c;对应工作表的12 ~ 16行&#xff0c;其中黄色列为需要统计的数…

IDEA中使用Git提交代码提示:您即将把CRLF行分隔符提交到Gt仓库。 建议将core.autocrlf Git特性设置为trUe,以免发生行分隔符问题。

IDEA中使用Git提交代码提示&#xff1a;您即将把CRLF行分隔符提交到Gt仓库。 建议将core.autocrlf Git特性设置为trUe,以免发生行分隔符问题。 问题背景&#xff1a; 在IDEA中&#xff0c;使用Git提交代码到远程仓库时&#xff0c;结果弹出一个警告窗口 问题原因&#xff1a; …

【测试开发】突破瓶颈必学技能——什么是k8s的核心概念?

目录 Docker 和K8s k8s中的重要概念 Master 节点 Node 节点 集群&#xff08;Cluster&#xff09; 标签&#xff08;Label&#xff09; 命名空间&#xff08;Namespace&#xff09; 容器组&#xff08;Pod&#xff09; 无状态部署&#xff08;Deployment&#xff09;…

【2023五一杯数学建模】 B题 快递需求分析问题 建模方案及MATLAB实现代码

【2023五一杯数学建模】 B题 快递需求分析问题 1 题目 请依据以下提供的附件数据和背景内容&#xff0c;建立数学模型&#xff0c;完成接下来的问题&#xff1a;问题背景是&#xff0c;网络购物作为一种重要的消费方式&#xff0c;带动着快递服务需求飞速增长&#xff0c;为我…

AVL 树(自平衡二叉搜索树) 介绍

AVL 树&#xff08;自平衡二叉搜索树) 介绍 前言 在介绍二叉搜索树的章节中提到&#xff0c;二叉搜索树可能退化为线性链表&#xff0c;失去作为二叉树的各种优势。那么过程中需要维持二叉树的形式&#xff0c;同时左右子树的深度差异可控&#xff0c;如果能实现这两个条件&a…

音视频 FFmpeg

文章目录 前言视频编解码硬件解码(高级)软解码(低级)软、硬解码对比视频解码有四个步骤Android 系统中编解码器的命名方式查看当前设备支持的硬解码 基础知识RGB色彩空间常见的格式对比YUV索引格式分离RGB24像素数据中的R、G、B分量 BMP 文件格式格式组成像素排列顺序RGB24格式…

autosar软件分层架构组成--汽车电子

介绍 autosar是汽车软件协会制定的一套软件标准 本文章所有图片来源于网络 一、分层架构 分层&#xff1a;3层 1.上层应用层&#xff08;Application Layer&#xff09; 2.中间件RTE(Runtime Environment) 3.下层的基础软件&#xff08;Basic Software&#xff09; 中间件R…

倾斜摄影超大场景的三维模型轻量化纹理压缩的关键技术

倾斜摄影超大场景的三维模型轻量化纹理压缩的关键技术 倾斜摄影超大场景的三维模型轻量化处理中纹理压缩是轻量化处理的重要手段之一&#xff0c;可以在保证模型真实感的前提下&#xff0c;减小数据体积、降低传输带宽和提高渲染性能。以下是几个关键的纹理压缩技术&#xff1a…

沁恒 CH32V208(一): CH32V208WBU6 评估板上手报告和Win10环境配置

目录 沁恒 CH32V208(一): CH32V208WBU6 评估板上手报告和Win10环境配置 CH32V208 CH32V208系列是沁恒32位RISC-V中比较新的一个系列, 基于青稞RISC-V4C内核, 最高144MHz主频, 64KB SRAM&#xff0c;128KB Flash, 供电电压2.5/3.3V. 这个型号的特点: 除了特有的硬件堆栈区、…

深度学习第J8周:Inception v1算法实战与解析

目录 一、Inception v1 1.简介 2. 算法结构 二、pytorch代码复现1.前期准备 2.代码复现 3.训练运行 3.2指定图片进行预测 三、总结 &#x1f368; 本文为[&#x1f517;365天深度学习训练营]内部限免文章&#xff08;版权归 *K同学啊* 所有&#xff09; &#x1f356; 作…

Linux:网络基础1

网络协议分层 所有网络问题&#xff0c;本质都是通信距离变长了&#xff0c;为了尽可能减少通信成本&#xff0c;定制了协议。 协议分层的优势&#xff1a; 软件设计方面的优势 - 低耦合 一般我们的分层依据: 功能比较集中&#xff0c;耦合度比较高的模块-- 一层 &#xff0c…

2023五一数学建模A题完整思路

已更新五一数学建模A题思路&#xff0c;文章末尾获取&#xff01; A题完整思路&#xff1a; A题是一个动力学问题&#xff0c;需要我们将物理学概念运用到实际生活中&#xff0c;我们可以先看题目 问题1&#xff1a; 假设无人机以平行于水平面的方式飞行&#xff0c;在空中投…

代码审计笔记之开篇

思想 代码审计是从软件测试发展而来&#xff0c;早起一般采用常规软件测试与渗透测试的手段来发现源码漏洞&#xff0c;但是随着软件规模的越来越大&#xff0c;架构越来越复杂&#xff0c;安全漏洞和后门也越来越多越来越隐蔽&#xff0c;这使得传统的软件测试方法很难检出源…

达梦数据库中注释的使用

在管理规模较大的数据库时&#xff0c;我们往往需要面对大量的表与视图&#xff0c;与此同时在表与视图中可能会存在着许多的字段&#xff0c;让人难以迅速分辨&#xff0c;不利于对于数据库对象的管理。除了在命名时&#xff0c;对于有意义的表、视图及列&#xff0c;应尽量赋…