数据库简介
常用的数据库
大型数据库:Oracle
中型数据库:Server 是微软开发的数据库产品,主要支持 windows 平台。
小型数据库:mySQL 是一个小型关系型数据库管理系统,开放源码 。(嵌入式不需要存储太多数据。)
SQLite 基础
SQLite 的源代码是 C,其源代码完全开放,是一个轻量级的嵌入式数据库。
特性:
1、零配置一无需安装和管理配置;
2、储存在单一磁盘文件中的一个完整的数据库;
3、数据库文件可以在不同字节顺序的机器间自由共享;
4、支持数据库大小至2TB;
5、嵌入式足够小,全部源码大致3万行 c 代码,250KB;
6、比目前流行的大多数数据库对数据的操作要快;
创建 SQLite 数据库:
-----------------两种方式都会用得到,重点是代码创建--------------------
手工创建:
使用 sqlite3 工具,通过手工输入 SQL 命令行完成数据库创建。
代码创建:
在代码中常常动态创建数据库 —— 在程序运行过程中,当需要进行数据库操作时,应用程序会首先尝试打开数据库,如果数据库并不存在,则程序将自动建立数据库,然后再打开数据库。
Linux 虚拟机中 sqlite3 的安装
在线安装方式
1) 确保虚拟机能联网
2)
● sudo apt-get update
● sudo apt-get install sqlite3
● sudo apt-get install libsqlite3-dev
● sudo apt-get install sqlitebrowser
安装软件及开发环境
—>sqlite3 数据库软件
—>sqlite3 数据库开发支持库
—>sqlite3 数据库操作软件
3) 安装成功后,终端输入以下指令,判断是否安装成功:
sqlite3 my.db
出现下列语句,表示安装成功,版本不一样无所谓,只要出现“sqlite>”即可,输入“.quit”退出数据库:
基础 SQL语句 的使用
两种命令格式:
sqlite3 系统命令
—— 以“.”开头;
SQL 命令
—— 以“;”结尾。
API 接口
(👆 跳转至 SQLite 官网)常用接口见 “sqlite3 编程”。
sqlite3 的使用:
1、创建一个数据库(数据库为空时,找不到图标);
2、在新建的数据库中,创建一张表,并设置主键;(表格创建成功后,数据库的图标显现)
3、向新建的表中插入数据;
4、查询表格中的数据;
5、打开图形化数据库;
6、删除表中一行;
7、删除整张表;
8、删除数据库;
sqlite3 编程
(👆 跳转至 SQLite 官网)
sqlite3_open
#include<sqlite3.h>
int sqlite3_open(char *path, sqlite3 **db);功能:打开 sqlite 数据库(或新建数据库)
参数:path: 数据库文件路径 db: 指向数据库句柄的指针 - 该二级指针指向一级指针,最终会存储打开的数据库的首地址
返回值:成功返回0,失败返回错误码(非零值) 使用: sqlite3 *db;if(sqlite3_open("stu.db", &db) != 0)fprintf(stderr, "Error: %s\n", sqlite3_errmsg(db));// sqlite3 自带的打印错误信息 值传递: 获取到值
地址传递: 修改值
sqlite3_close
#include<sqlite3.h>
int sqlite3_close(sqlite3 *db);功能:关闭 sqlite 数据库
参数:db
返回值:成功返回0,失败返回错误码
sqlite3_errmsg
#include<sqlite3.h>
const char *sqlite3_errmsg(sqlite3 *db);
功能: 打印错误信息
参数:db
返回值:返回错误信息
使用(e.g.): fprintf(stderr, "sqlite3_open failed: %s\n", sqlite3_errmsg(db));
sqlite3_exec
原型:int sqlite3_exec(sqlite3 *db, /* An open database */const char *sql, /* SQL to be evaluated */int (*callback)(void*, int, char**, char**), /* Callback function */void *arg, /* 1st argument to callback */char **errmsg /* Error msg written here */);功能:执行sql语句;
参数:sqlite3 *db: 指定要操作的数据库句柄指针;char *sql: 指定要执行的sql语句;int (*callback)(void*, int, char**, char**):回调函数; 该函数指针可以指向返回值是int类型,参数列表是(void*, int, char**, char**)的函数void *arg: 传递给回调函数的第一个参数; - 类似线程函数传参,需强转 - 不传参可以填 NULLchar **errmsg: 该二级指针指向的一级指针会存储错误信息的首地址,错误信息存储在静态存储区;(定义一个一级指针即可)
返回值:成功:返回 SQLITE_OK,即 0;失败:返回 error_code,即非 0
// sqlite3.c#include <stdio.h>
#include <sqlite3.h>int num;
char buf[128] = {};
typedef struct{int id;char name[32];float score;
} STU; int main(int argc, char const *argv[])
{sqlite3 *db = NULL;if (sqlite3_open("/home/hq/MyFolders/sqlite3/testdb.db", &db)){fprintf(stderr, "Sqlite3_open failed: %s\n", sqlite3_errmsg(db));return -1;}char *errmsg = NULL;if (sqlite3_exec(db, "CREATE TABLE stu(id int primary key, name char, score float);",NULL, NULL, &errmsg)){fprintf(stderr, "Failed to create a table named \"stu\": %s\n", errmsg);return -1;}if (sqlite3_exec(db, "INSERT INTO stu VALUES(2023052201, \"Frank\", 95);", NULL, NULL, &errmsg)){fprintf(stderr, "Failed to insert: %s\n", errmsg);return -1;}printf("Please input a number:\n");scanf("%d", &num);STU stu;for (int i = 0; i < num; i++){scanf("%d %s %f", &stu.id, stu.name, &stu.score);sprintf(buf, "INSERT INTO stu VALUES(%d, \"%s\", %f);", stu.id, stu.name, stu.score);if (sqlite3_exec(db, buf, NULL, NULL, &errmsg)){fprintf(stderr, "Failed to insert: %s\n", errmsg);return -1;}}sqlite3_close(db);return 0;
}
运行结果如下:
sqlite3_exec 的 回调函数 callback
int callback(void *arg, int columns, char **column_text, char **column_name);功能:sqlite3_exec 每找到一条满足条件的记录,就会执行一次回调函数。
参数:void *arg: sqlite3_exec 的第四个参数传入;int columns: 查询结果的列数;char **column_text:该二级指针指向一个指针数组,数组中的元素都是 char*类型 的指针,指针指向查询结果的内容;char **column_name:该二级指针指向一个指针数组,数组中的元素都是 char*类型 的指针,指针指向查询结果的列名;
返回值:成功时候必须返回0,该返回值会返回给 sqlite3_exec 函数,如果没有返回0,则 sqlite3_exec 会认为回调函数运行失败,从而导致 sqlite3_exec 运行失败。
// sqlite3.c#include <stdio.h>
#include <sqlite3.h>int num;
char buf[128] = {};
typedef struct{int id;char name[32];float score;
} STU; int select_cback(void *arg, int columns, char **column_text, char **column_name){printf("columns: %d\n", columns);printf("column_name: ");for (int i = 0; i < columns; i++)printf("%-12s", column_name[i]); putchar(10);printf("column_text: ");for (int i = 0; i < columns; i++)printf("%-12s", column_text[i]);putchar(10);return 0;
}int main(int argc, char const *argv[])
{sqlite3 *db = NULL;if (sqlite3_open("/home/hq/MyFolders/sqlite3/testdb.db", &db)){fprintf(stderr, "Sqlite3_open failed: %s\n", sqlite3_errmsg(db));return -1;}char *errmsg = NULL;if (sqlite3_exec(db, "CREATE TABLE stu(id int primary key, name char, score float);",NULL, NULL, &errmsg)){fprintf(stderr, "Failed to create a table named \"stu\": %s\n", errmsg);}if (sqlite3_exec(db, "INSERT INTO stu VALUES(2023052201, \"Frank\", 95);", NULL, NULL, &errmsg)){fprintf(stderr, "Failed to insert: %s\n", errmsg);return -1;}printf("Please input a number:\n");scanf("%d", &num);STU stu;for (int i = 0; i < num; i++){scanf("%d %s %f", &stu.id, stu.name, &stu.score);sprintf(buf, "INSERT INTO stu VALUES(%d, \"%s\", %f);", stu.id, stu.name, stu.score);if (sqlite3_exec(db, buf, NULL, NULL, &errmsg)){fprintf(stderr, "Failed to insert: %s\n", errmsg);return -1;}}if (sqlite3_exec(db, "SELECT * FROM stu;", select_cback, NULL, &errmsg)){fprintf(stderr, "Select failed: %s\n", errmsg);return -1;}printf("------------------------\n");if (sqlite3_exec(db, "SELECT name FROM stu WHERE score = 92;", select_cback, NULL, &errmsg)){fprintf(stderr, "Select failed: %s\n", errmsg);return -1;}sqlite3_close(db);return 0;
}
运行结果如下:
sqlite3_get_table(不回调查询)
int sqlite3_get_table(sqlite3 *db, const char *sql, char ***resultp, int *nrow, int *ncolumn, char **errmsg);功能:执行SQL操作
参数: db: 数据库句柄 sql: SQL语句resultp: 用来指向sql执行结果的指针 (该参数为三级指针,指向二级指针,所以需定义二级指针变量) nrow: 该一级指针指向的内存空间中存储结果的行数,(一级指针指向变量地址),包括表头ncolumn: 该一级指针指向的内存空间中存储结果的列数 errmsg: 该二级指针指向的一级指针会存储错误信息首地址
返回值:成功返回SQLITE_OK,失败返回错误码
// sqlite3.c#include <stdio.h>
#include <sqlite3.h>int num;
char buf[128] = {};
typedef struct{int id;char name[32];float score;
} STU; int main(int argc, char const *argv[])
{sqlite3 *db = NULL;if (sqlite3_open("/home/hq/MyFolders/sqlite3/testdb.db", &db)){fprintf(stderr, "Sqlite3_open failed: %s\n", sqlite3_errmsg(db));return -1;}char *errmsg = NULL;if (sqlite3_exec(db, "CREATE TABLE stu(id int primary key, name char, score float);",NULL, NULL, &errmsg)){fprintf(stderr, "Failed to create a table named \"stu\": %s\n", errmsg);}if (sqlite3_exec(db, "INSERT INTO stu VALUES(2023052201, \"Frank\", 95);", NULL, NULL, &errmsg)){fprintf(stderr, "Failed to insert: %s\n", errmsg);return -1;}printf("Please input a number:\n");scanf("%d", &num);STU stu;for (int i = 0; i < num; i++){scanf("%d %s %f", &stu.id, stu.name, &stu.score);sprintf(buf, "INSERT INTO stu VALUES(%d, \"%s\", %f);", stu.id, stu.name, stu.score);if (sqlite3_exec(db, buf, NULL, NULL, &errmsg)){fprintf(stderr, "Failed to insert: %s\n", errmsg);return -1;}}char **resultp;int nrow, ncolumn;if (sqlite3_get_table(db, "SELECT * FROM stu;", &resultp, &nrow, &ncolumn, &errmsg)){fprintf(stderr, "Failed to select: %s\n", errmsg);return -1;}printf("--------------------\n");for (int i = 0; i <= nrow; i++){ // 要包含表头for (int j = 0; j < ncolumn; j++)printf("%-12s", resultp[i*ncolumn+j]);putchar(10);}sqlite3_close(db);return 0;
}
运行结果如下: