链接sqlite

简介: 链接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) 等。


注意事项:


在使用sqlite3_exec函数时,需要特别注意SQL注入问题,应该避免直接在SQL语句中拼接用户输入的字符串,而应该采用参数绑定的方式。

在使用回调函数时,需要根据具体情况做好内存管理,避免内存泄漏等问题。

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基础


我的当前数据库信息:

d42b540e9ff641fcb177137342d17a7a.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 数据库操作中的查询操作。


它的参数包括:


void *NotUsed:这是一个不使用的指针,通常可以忽略。

int argc:这是一个整数,表示查询结果集的列数。

char **argv:这是一个字符数组指针,它包含每个查询结果的值。每个元素都是一个字符串,存储了对应列的值。

char **azColName:这是一个字符数组指针,它包含每个查询结果的列名。每个元素都是一个字符串,存储了对应列的名称。

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

5.演示结果

b4cae6cc396ca8e1da82e225433e7c16.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

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。

Cursor()


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


execute(sql[, parameters])


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


sql:要执行的 SQL 命令。

parameters:可选参数,用于替换 SQL 命令中的占位符。

fetchone()


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


fetchmany([size])


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


fetchall()


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


commit()


提交当前事务。


rollback()


回滚当前事务。


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语言简单。

相关文章
|
12天前
|
关系型数据库 MySQL 数据库
Python处理数据库:MySQL与SQLite详解 | python小知识
本文详细介绍了如何使用Python操作MySQL和SQLite数据库,包括安装必要的库、连接数据库、执行增删改查等基本操作,适合初学者快速上手。
81 15
|
1月前
|
存储 SQL 数据库
数据库知识:了解SQLite或其他移动端数据库的使用
【10月更文挑战第22天】本文介绍了SQLite在移动应用开发中的应用,包括其优势、如何在Android中集成SQLite、基本的数据库操作(增删改查)、并发访问和事务处理等。通过示例代码,帮助开发者更好地理解和使用SQLite。此外,还提到了其他移动端数据库的选择。
43 8
|
2月前
|
Web App开发 SQL 数据库
使用 Python 解析火狐浏览器的 SQLite3 数据库
本文介绍如何使用 Python 解析火狐浏览器的 SQLite3 数据库,包括书签、历史记录和下载记录等。通过安装 Python 和 SQLite3,定位火狐数据库文件路径,编写 Python 脚本连接数据库并执行 SQL 查询,最终输出最近访问的网站历史记录。
44 4
|
2月前
|
Java 关系型数据库 MySQL
springboot学习四:springboot链接mysql数据库,使用JdbcTemplate 操作mysql
这篇文章是关于如何使用Spring Boot框架通过JdbcTemplate操作MySQL数据库的教程。
77 0
springboot学习四:springboot链接mysql数据库,使用JdbcTemplate 操作mysql
|
2月前
|
存储 关系型数据库 数据库
轻量级数据库的利器:Python 及其内置 SQLite 简介
轻量级数据库的利器:Python 及其内置 SQLite 简介
70 3
|
2月前
|
数据库连接 网络安全 数据库
网站链接数据库失败,重启网站好了
网站链接数据库失败,重启网站好了
|
2月前
|
应用服务中间件 PHP Apache
PbootCMS提示错误信息“未检测到您服务器环境的sqlite3数据库扩展...”
PbootCMS提示错误信息“未检测到您服务器环境的sqlite3数据库扩展...”
|
2月前
|
Java 关系型数据库 数据库连接
SpringBoot项目使用yml文件链接数据库异常
【10月更文挑战第3天】Spring Boot项目中数据库连接问题可能源于配置错误或依赖缺失。YAML配置文件的格式不正确,如缩进错误,会导致解析失败;而数据库驱动不匹配、连接字符串或认证信息错误同样引发连接异常。解决方法包括检查并修正YAML格式,确认配置属性无误,以及添加正确的数据库驱动依赖。利用日志记录和异常信息分析可辅助问题排查。
315 10
|
2月前
|
Java 关系型数据库 MySQL
SpringBoot项目使用yml文件链接数据库异常
【10月更文挑战第4天】本文分析了Spring Boot应用在连接数据库时可能遇到的问题及其解决方案。主要从四个方面探讨:配置文件格式错误、依赖缺失或版本不兼容、数据库服务问题、配置属性未正确注入。针对这些问题,提供了详细的检查方法和调试技巧,如检查YAML格式、验证依赖版本、确认数据库服务状态及用户权限,并通过日志和断点调试定位问题。
164 6
|
3月前
|
存储 API 数据库
QML使用Sqlite数据库存储ListModel数据
本文介绍了在QML中使用Sqlite数据库存储ListModel数据的方法,包括如何创建数据库、读取数据、动态添加和删除数据,以及如何在程序启动和退出时与数据库同步数据。
下一篇
DataWorks