0.数据库大纲
数据库是什么 ?
如何在在命令行使用SQL语句操作数据库 ?如何在C/C++程序中操作数据库
1.数据库和数据库管理系统及数据库系统
数据库是一个存储数据(电子化表格)的仓库.
数据库, 简单来说可以看做是一个电子化的文件柜,—> 存储电子文件的工具,
用户可文件中的数据进行 , 增 , 删 , 改 , 查等操作.
其实我们常说的"数据库" 值的是 “数据管理系统”.
数据库(DataBase) :存储数据(电子化表格)的仓库.
数据库管理系统(DBMS DataBase Management System) : 数据库对外操作数据的接口.
数据库系统(DBS DataBase System) : 带有数据库的计算机系统, 一般由数据库,数据库管理系统
(及其开发工具),相关的硬件,软件和各类人员组成.
数据库系统 包含 数据库 和 数据库管理系统.
数据库管理系统(DBMS)是为数据库设计的计算机软件,一般都是可以对数据进行, 增 , 删 , 改 , 查等操作.
我们数据库(DB) 和 数据库管理系统(DBMS) 之间的关系和现实中 :
excel中学生表(多个表) 和 excel关系.
1.关系型数据库(Relational Database)
关系型数据库是创建在关系模型(E-R模型)基础上的数据库(数据和数据是存在关系的)关系 ? 表格
表 是行和列的形式组织起来的数据的集合;
关系型数据库是由多个表组成的数据库.
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yACgTkaP-1667307229748)(…/3-pic/image-20221101093019425.png)]
行 : 一条完整的记录 , 包含多个不同的属性.
列 : 具有相同属性的数据集合 .
表中的每一行称为一条记录 , 一列称为一个字段(属性), 每一列的标题称为字段名.
如果给关系型数据库中的每一个关系取一个名字 , 则一个有n个字段的关系表可以表示为 :
关系表名(字段1 , 字段2 , 字段3 , … , 字段n);
如 : 学生信息表(学号 , 姓名 , 地址 , 班级)
常用的关系型数据库(数据库管理系统有很多)
Oracle
Mysql
Sqlite3 轻量级的开源的关系型数据库 , 很适合在嵌入式设备上使用
SQL server
DB2
关系型表格如何创建 ?
E-R模型(可以描述现实生活中的关系模型)
实体-关系模型
实体-关系模型图 ,由三个部分组成 :
实体 : 客观存在的事物, 用矩形表示 , 如 : 学生 ,成绩
联系 : 实体之间的联系, 用菱形表示 , 如 : 考试
属性 : 实体所具有的某一个属性 ,用椭圆表示 ,如 : 学号, 姓名
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ij9jBgZd-1667307229751)(…/3-pic/image-20221101095015125.png)]
一般来说 ,一个实体就会对应一个表格 ,实体的属性就是对应表格中的字段 ,多个表格可以通过 主键 和 外键相互联系
主键
关系型数据库中一条记录中有若干个属性 ,若一个属性能唯一的标识一条记录.
该属性就可以设置成一个主键.
如 :
学生信息表(学号 ,姓名 ,地址 ,班级)
其中每一个学生的学号是唯一的, 学号就是学生表中的一个主键.
课程表(课程编号 ,任课老师 ,开课时间)
其中的课程编号是唯一的,课程编号就是课程表中的一个主键
成绩表中单一的一个属性无法唯一标识一条记录 , 学号 和 科目的组合可以
唯一标识一条记录 , 主键可以是属性的集合.
外键
在当前表中不是主键 ,但是在其他表中是主键.
成绩表中的学号不是成绩表的主键 ,但是他和学号表中的学号是对应的,
并且学生表中的学号是学生表的主键 ,则把成绩表中的学号叫做学生表的外键.
主键 和 外键主要是维护关系数据的完整性.
a . 主键能在当前表中唯一标识一条一条记录.
b.外键是用于和另外一张表的关联.
2.关系型数据库语言 SQL语言
SQL (Structtured Query Language)结构化的查询语言 ;
是一种通用的功能强大的关系型数据库语言 .
结构化的查询语言包含六个部分 :
数据查询语言 DQL Data Quary Language
从数据库中获取/查询数据(SELECT)
- 数据库的操作语言 DML Data Manipulation Language
用来操作数据库中的用户数据 ,包括增加数据(INSERT) ,删除数据(DELETE) ,
修改数据(UPDATE)
- 事物处理语句
确保DML语句的作业及时的更新到数据库中;
数据控制语言 DCL
数据定义语言 DDL Data Define Language
用来操作数据库中的元数据
包括创建一个表 ,删除一个表 , 修改一个表中的字段.
- 指针控制语言
数据查询语言 DQL Data Quary Language
从数据库中获取/查询数据(SELECT)
数据库的操作语言 DML Data Manipulation Language
用来操作数据库中的用户数据 ,包括增加数据(INSERT) ,删除数据(DELETE) ,
修改数据(UPDATE)
数据定义语言 DDL Data Define Language
用来操作数据库中的元数据
包括创建一个表 ,删除一个表 , 修改一个表中的字段.
所有的SQL语句都是在命令行中执行的 执行sqlite3命令就要进入sqlite3命令行 sqlite3 .help .quit .exit 退出sqlite3的程序
(1) 创建一个sqlite数据库(里面没有数据)对象
终端 :
sqlite3 数据库对象名字 //打开或创建一个数据库 如 : sqlite3 test.db
通过SQL语句操作数据库都是在sqlite3的命令行程序中 :
注意 :
a.在sqlite3命令下面 ,SQL语句以分号(" ; ")结束
b.SQL语句支持大小写 ,但是在实际使用中建议使用大写 ;
因为所有的语句在执行的时候 ,都是先转换为大写的形式.
(2) 在数据库对象(test.db)中创建一个表
CREATE TABLE : 用来创建一个关系表
语法 :
CREATE TABLE 表名( 列名1 数据类型 "约束", 列名2 数据类型 "约束", 列名3 数据类型 "约束", ... 列名n 数据类型 "约束" ); 表名 : 数据库中关系表的名字 列名 : 关系表中的字段名 数据类型 : 说明字段中的数据的类型 integer(size) 此字段必须为整数 size规定数字的最大的位数 int(size) smallint(size) ... decimal(size,d) 容纳带小数的数字,size规定数字的最大位数,d表示小数点右侧的最大位数 float double real char(size) 固定从长度的字符串 ,size规定字符串的长度 varchar(size) 可变长度的字符串,size规定字符串的最大长度 text data 日期 2022/11/1 2022-11-1 约束 : NOT NULL 此字段不能为空 UNIQUE 此字段唯一(不能重复) PRIMARY KEY 主键 ,主键必须是 NOT NULL AND UNIQUE FOREGIN KEY 外键 ,这一列在其他表中是主键,在自己的表中不是主键 CHECK 用于限制数据的范围 CHECK SCORE>=0 AND SCORE<=100
例子 : 在test.db中创建一个学生表
STUINFO(学号 ,名字 ,地址 ,分数)
CREATE TABLE STUINFO( NUM int(4) PRIMARY KEY, NAME varchar(255) NOT NULL, ADDR varchar(255) NOT NULL, SCORE real(4) CHECK(SCORE>=0 AND SCORE<=100) );
CREATE TABLE STUINFO(NUM int(4) PRIMARY KEY,NAME varchar(255) NOT NULL,ADDR varchar(255) NOT NULL,SCORE real(4) CHECK(SCORE>=0 AND SCORE<=100)); CREATE TABLE STU(NUM int(4) PRIMARY KEY,NAME varchar(255) NOT NULL,ADDR varchar(255) NOT NULL,SCORE real(4) CHECK(SCORE>=0 AND SCORE<=100));
查询数据库中的表格
.table
查看表格的结构
.schema
删除数据库中的一个表
语法 :
DROP TABLE 表名; 如 : DROP TABLE STUTEST;
修改表的结构 :
a . 修改表名
ALTER TABLE 表名 RENAME TO 新名字; 如 : ALTER TABLE STU RENAME TO STUINFO;
b . 增加字段
ALTER TABLE 表名 ADD 字段名 字段类型; 如 : ALTER TABLE STUINFO ADD TEL INT;//在STUINFO中增加一个新的字段
(3) 向表中插入新行(一条新的记录)
INSERT INFO : 用于向表格插入新行
语法 :
INSERT INFO 表名 VALUES(值1,值2,...,值n); INSERT INFO 表名(字段1,字段2,...) VALUES(值1,值2,...,值n); 如 : INSERT INTO STUINFO VALUES(1,"zhangsan","cs",88,10086); INSERT INTO STUINFO(NUM,NAME,ADDR,SCORE) VALUES(2,"lisi","cs",89);
(4) SELECT用于从表中选取数据 ,把结果列举出来
语法 :
SELECT 列名1,列名2... FROM 表名 WHERE 列 运算符 值;
SELECT * FROM 表名;//查看表中所有的信息 如 : SELECT * FROM STUINFO; INSERT INTO STUINFO VALUES(3,"wangwu","bj",68,10000); INSERT INTO STUINFO VALUES(4,"zhaoliu","jx",99,119);
运算符 :
= 等于 <> 不等于 > 大于 < 小于 BETWEEN AND SELECT * FROM STUINFO WHERE NUM=1;//查看学号为1的学生信息 SELECT * FROM STUINFO WHERE NUM<>1;//查看学号不为1的学生信息 SELECT * FROM STUINFO WHERE NUM>3;//查看学号大于3的学生信息 //查看学生表中学号为2-4之间的学生信息 SELECT * FROM STUINFO WHERE NUM BETWEEN 2 AND 4;
WHERE 表示条件查询 如果有多个条件 : AND 并且 OR 或者 //查看学号为2或者电话为10086的学生信息 SELECT * FROM STUINFO WHERE NUM=2 OR TEL=10086; 限定 + 排序 SELECT * FROM 表名 ORDER BY 字段 ASC/DESC //查看学生表中根据分数降序排序的前三条记录 SELECT * FROM STUINFO ORDER BY SCORE DESC LIMIT 3; 查找模糊值(like) //查找姓zhang的学生信息 SELECT NAME,NUM,TEL FROM STUINFO WHERE NAME LIKE 'zhang%'; SELECT NAME,NUM,TEL FROM STUINFO WHERE NAME LIKE '%i%';
(5) 多表查询–多表连接
CREATE TABLE KCB(NUM INT,KCH INT PRIMARY KEY,NAME VARCHAR,SCORE REAL); INSERT INTO KCB VALUES(1,1,"yuwen",89); INSERT INTO KCB VALUES(1,2,"shuxue",68); INSERT INTO KCB VALUES(1,3,"yingyu",70);
语法 :
SELECT 表名.列名1,表名.列名2... FROM 表名1,表名2 WHERE 列 运算符 值; 如果在多表查询中不指定连接条件,就会自动的连接,导致将一个表中所有的行 都连接到另一个表中所有的行上面 --- 卡迪尔积 如果第一个表中有50行,第二个表中有10行,得到的结果就有500 多表查询的时候,实际上是从产生的"卡迪尔积"的结果中得到满足条件的记录.
SELECT STUINFO.NUM,STUINFO.NAME,STUINFO.ADDR,KCB.NUM,KCB.KCH,KCB.SCORE FROM STUINFO,KCB; SELECT STUINFO.NUM,STUINFO.NAME,STUINFO.ADDR,KCB.NUM,KCB.KCH,KCB.SCORE FROM STUINFO,KCB WHERE STUINFO.NUM=KCB.NUM;
.header on //列举结果的时候,会显示表头 .mode colum //按照列的方式显示结果 这样看起来会顺眼一些
SQL语句 ,需要掌握的有 :
创建一个表
CREATE TABLE
删除一个表
DROP TABLE
修改一个表的元数据
ALTTER TABLE
查询数据
SELECT
增加表中的用户数据
INSERT INTO
删除表中的用户数据
DELETE FROM
修改表中的用户数据
UPDATE
4.数据库对C/C++的API接口
通过C/C++程序去操作数据库
如何通过API函数接口 ,执行SQL语句
Sqlite3的API函数接口的核心部分 :
两大对象 和 八大函数
两大对象
数据库连接对象(The Database Connection Object)
数据库连接句柄/数据库自己的文件描述符 ,表示一个已经打开的数据库
sqlite3 * 代表你打开的那一个sqlite3的数据库文件(test.db);
后续对数据库的所有操作都需要通过这个连接对象.
SQL语句对象(The prepare Statement Object)
sqlite3_stmt
就是一条准备好的SQL语句.
操作数据库的标准语言就是SQL语句 ,在这里 ,使用准备好的SQL语句对象
表示的SQL语句去操作数据连接对象表示的数据库.
利用SQL语句操作数据库的流程(八大函数)
1.建立连接
2.打开/创建一个数据
sqlite3_open();//打开或创建一个sqlite3的数据库连接对象
3.利用SQL语句对象操作数据库
sqlite3_prepare_v2();//准备一个SQL语句对象 sqlite3_bind_*();//绑定参数 sqlite3_step();//执行sql语句 sqlite3_column();//输出查询到的数据库的数据 sqlite3_finalize();//释放资源,销毁SQL语句对象 sqlite3_exec();
4.关闭数据库
sqlite3_close();//关闭一个数据库连接对象
5.具体的API函数的使用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hipXwlnD-1667980048382)(…/3-pic/image-20221102102404172.png)]
(1) 打开数据
sqlite3_open
sqlite3 * 代表你打开的那一个sqlite3的数据库文件(test.db) ,
后续对数据的所有操作都需要通过这个连接对象.
SQLITE_API int sqlite3_open( const char *filename, /* Database filename (UTF-8) */ sqlite3 **ppDb /* OUT: SQLite db handle */ ); filename : 要打开的sqlite3的数据库名字(带路径) ppDb : 二级指针,用来保存打开的数据库的连接对象(连接句柄) ppdb指向的内存是用来保存打开的数据库对象的地址. 返回值 : 成功 返回SQLITE_OK 失败 返回其他值
(2) 关闭一个sqlite3数据库连接对象
sqlite3_close
SQLITE_API int sqlite3_close(sqlite3*); 参数为你要关闭的数据库指针
(3) 关于SQL语句对象的API函数(准备)
sqlite3_stmt 这个结构体来描述一个SQL语句对象
我们的应用程序都是通过SQL语句对象去发送SQL语句的.
sqlite3_stmt * stmt;//SQL语句对象的指针 sqlite3_prepare_v2();//准备一个SQL语句
SQLITE_API int sqlite3_prepare_v2( sqlite3 *db, //数据库连接对象,语句作用在哪一个数据库上 const char *zSql, //要执行的原始的sql语句的字符串形式 int nByte, //原始sql语句的长度 sqlite3_stmt **ppStmt, //OUT: 用来保存解析后的SQL语句对象 const char **pzTail //OUT: 指向原始的sql语句中未使用的部分 ); nByte : 原始sql语句的长度(原始语句可以包含多条SQL语句) <0 :编译到zSql指向的sql语句的第一个'\0'为止. >0 :编译到zSql指向的sql语句的nByte指定的字节为止. =0 :什么都不编译. ppStmt : 二级指针,用来保存解析后的SQL语句对象的地址 要改变指针变量的值,指针不在作用范围内,只能间接访问,把指针变量的地址 传入函数,在函数的内部就可以改变指针变量的值. 在函数内部,可能会让指针变量指向一个准备好的SQL语句对象. pzTail :二级指针,用来指向原始的SQL语句总未使用的部分(如果不需要,也就是 说zSql指向的字符串中只有一条SQL语句,则可以指定为NULL); 可以实现一个字符串中写多条SQL语句,准备一条语句后,指针指向的位置为未使用的部分. sqlite3_stmt * stmt;//SQL语句对象的指针 const char *p = NULL; sqlite3_prepare_v2(test.db,str,-1,&stmt,&p); 在函数执行完毕后,stmt指向准备好的SQL语句对象 p指向str中未使用的部分. 返回值 : 成功 返回SQLITE_OK 失败 返回其他值
(4) 执行一条准备好的SQL语句(SQL语句对象)
sqlite3_step
SQLITE_API int sqlite3_step(sqlite3_stmt*); stmt : 指针,指向你准备好的SQL语句对象,也是你要执行的SQL语句对象 返回值 : 成功 返回SQLITE_DONE 失败 返回其他值
(5) 释放资源
sqlite3_finalize
SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt);
在prepare的时候,很有可能让stmt指针指向了动态分配的内存空间,通过函数释放所有的资源.
-
<1> pzTail :二级指针,用来指向原始的SQL语句总未使用的部分(如果不需要,也就是
说zSql指向的字符串中只有一条SQL语句,则可以指定为NULL); -
<2> 从标准输入往数据库中添加数据
-
<3> 读取文件数据并添加到数据库中
-
<4> 通过绑定索引值往数据库中添加数据
(6) 一步查询的执行操作(sqlite3_exec)
sqlite3_exec()接口[sqlite3_prepare_v2 , sqlite3_step , sqlite3_finalize ]集合,他可以
让应用程序运行多个SQL语句 ,而不必使用大量的C语言代码.
SQLITE_API int sqlite3_exec( sqlite3*, //数据库连接对象 const char *sql, //是一条你要执行的SQL语句 int (*callback)(void*,int,char**,char**), //回调函数,只有在SELECT的时候才有用 void *, //回调函数的第一个参数 char **errmsg //出错信息的指针 );
int (*callback)(void*,int,char**,char**) 函数指针,执行你要执行的函数,函数的返回值为int,有四个参数 当调用sqlite3_exec 去执行SELECT语句的时候,就会执行这个回调函数, 主要作用是处理SELECT的结果信息.
int (*callback)(void*,int,char**,char**) 回调函数参数的详细信息 : 第一个参数是指针,可以传入用户自己的数据 第二个参数是执行SELECT语句后,查询到结果的列数 第三个参数是一个指向字符串的指针数组,就是结果数据的每一列信息 第四个参数是一个指向字符串的指针数组,就是结果数据每一列的表头信息
sqlite3_exec参数详解 :
第一个参数是你要操作的数据连接对象 第二个参数是以分号分隔的SQL的原始语句 第三个参数如果为空,表示没有回到函数,如果不为空,在执行SELECT语句的时候 会调用回调函数,回调函数主要是处理SELECT查询到的结果 第三四个参数作为回调函数的第个参数(作用用户自定义) 第五个参数不为NULL,则将错误信息写入[sqlite3_nalloc]分配内存中, 并且让第五个参数指向的分配的内存,为了避免内存泄漏,应用程序在处理完 错误信息后,通过sqlite3_free释放第五个参数指向的内存.
只有在执行SELECT语句的时候,才需要回调函数
SELECT有多少条记录,就会执行多少次回调函数