express中间件: 可以在请求到达服务器后, 先经过中间件函数的处理, 然后再转交给路由进行业务逻辑的运行
中间件 - 就是一个函数, 而且所有的中间件都共享同一个req和res对象
中间件分为:
全局中间件: 在路由以上 - 任何请求过来从上到下被中间件处理 - 注意一定要最后执行next()才能往下运行
app.use(函数体) // 在路由以上使用
app.get()
app.post()
局部中间件: 在某个路由命中后, 才执行的中间件叫局部中间件, 只对这个路由生效
app.get("/api/list", (req, res, next) => {
next();
})
错误中间件: 一般写在整个项目路由的最后, 而且参数有4个, 需要上一级next()传递下来信息才可以出发
app.use((err, req, res, next) => {
})
内置中间件:
自定义中间件
第三方中间件
路由器中间件
const express = require("express");
const router = express.Router();
router.get()
跨域问题解决:
以前数据保存在变量上, 或者保存在浏览器本地, 现在我们知道数据真正在哪里了
什么是数据库
数据库 (database) 是用来组织、存储和管理数据的仓库。
为什么学数据库
当今世界是一个充满着数据的互联网世界,充斥着大量的数据。数据的来源有很多,比如出行记录、消费记录、浏览的商品、发送的消息等等。除了文本类型的数据,图像、音乐、声音都是数据(存储的是文件的地址)
为了方便管理互联网世界中的数据,就有了数据库管理系统的概念(简称:数据库)。用户可以对数据库中的数 据进行新增、查询、更新、删除等操作
学完数据库能干什么
我们可以设计数据存放的结构, 进行有序和结构化的管理, 方便我们进行查找和使用. 现在的大数据和所有你用的网站以及应用都离不开数据库在后面默默的支持.
听没听说过, 删库跑路, 可见数据库的重要性.
常见的数据库及分类
市面上的数据库有很多种,最常见的数据库有如下几个:
其中,MySQL、Oracle、SQL Server 属于传统型数据库(又叫做:关系型数据库 或 SQL 数据库),这三者的 设计理念相同,用法比较类似。
而 Mongodb 属于新型数据库(又叫做:非关系型数据库 或 NoSQL 数据库),它在一定程度上弥补了传统型 数据库的缺陷。
MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Oracle 旗下产品
我们常说数据库,其实只是一个泛指。那么数据库的结构是怎样的呢?
真正存储数据的是数据表。数据表和我们见过的Excel表格结构基本相同。
数据表的结构和excel一模一样。
id(不允许重复) | name | age | sex | tel |
---|---|---|---|---|
1 | 小明 | 23 | 男 | 13200008888 |
2 | 小传 | 23 | 男 | 13300008888 |
3 | 小黑 | 25 | 男 | 18866669999 |
4 | 老智 | 32 | 女 | 13200008888 |
安装MySQL
MySQL 服务器软件(phpStudy) ---- 存储数据,可以创建数据库、数据表 - 下载地址: https://www.xp.cn/
安装Navicat软件
MySQL图形化管理工具(Navicat) — 可以使用它管理(创建、增删改查等等)数据库
启动MySQL
phpStudy软件打开后, 启动MySQL服务 - 电脑就可以提供数据库服务了, 就像node xxx.js 启动web服务
Navicat使用
一定要确保mysql启动了, 才能让navicat链接这个数据库服务, 操作这个电脑里的数据库里的东西
连接到MySQL服务器
打开 Navicat软件。
创建 - 数据库
创建 - 表
比如创建一个学生信息表:
id(不允许重复) | name | age | sex | tel |
---|---|---|---|---|
1 | 小明 | 23 | 男 | 13200008888 |
2 | 小传 | 23 | 男 | 13300008888 |
3 | 小黑 | 25 | 男 | 18866669999 |
4 | 老智 | 32 | 女 | 13200008888 |
对于一张表,最重要的是表头的设计
对于数据库中的数据表,最重要的设计也是表头,只不过在数据库中
把表头叫做字段
下面是关于id的设计:
下面是完整的创建表:
名(表头) | 类型 | 长度 | 不是null | 键 | 其他 |
---|---|---|---|---|---|
id | int | √ | 勾选自动递增 | ||
name | varchar | 20 | √ | ||
age | int | ||||
sex | varchar | 2 |
id – 自动递增 – √
最后保存,填表名 student
。
其他补充点
SQL(英文全称:Structured Query Language)是结构化查询语言,专门用来访问和处理数据库的编程语言。
三个关键点
SQL能做什么
打开navicat的执行SQL语句的功能
基本的格式: insert into 表名 …
方式一:指定字段和值,只要字段和值对应即可。和顺序无关
格式: insert into 表名 (字段, 字段, ...) values (值, 值, ...)
例如:
insert into student (name, age, sex) values ('虚空恐惧', 98, '男')
方式二:和顺序有关,因为没指定字段,所以值必须是所有的值,而且顺序和表中字段的顺序要一致
格式: insert into 表名 values (值, 值, ...)
例如:
insert into student values (null, '光辉女郎', 28, '女', 13900202020)
方式三:使用set里设置新数据的值,没有顺序关系
格式: insert into 表名 set 字段=值, 字段=值, ....
例如:
insert into student set age=30, sex='男', name='李青', tel=13900409202
语法格式:
不区分
大小写。-- 查询某几个字段带值
SELECT 字段1, 字段2,... FROM 表名
select 字段1, 字段2,... from 表名
例如:
select id, name FROM student
-- 查询所有的字段带值
SELECT * FROM 表名
例如:
select * from stduent
-- 带条件的查询
SELECT * FROM 表名 WHERE 条件 ORDER BY 排序字段 LIMIT 开始位置下标, 长度
例如:
select * from student where age > 18 ORDER BY age LIMIT 0, 2
练习1: 查询所有学生的姓名和年龄
SELECT id,name FROM student;
练习2: 查询全部学生的全部信息
SELECT * FROM student;
select field1, field2… from 表名 查询表中的所有数据
where 可以使用条件来筛选查询出的结果
-- 查询年龄小于20的学生
-- select * from student where 条件
-- select * from student where age < 20
-- 查询age大于18的女学生
-- select * from student where age > 18 and sex = '女'
-- 查询年龄大于等于20小于等于30的学生
-- select * from student where age>=20 and age<=30
-- select * from student where age between 20 and 30
通配符:
%: 代表任意长度(包括0)的任意字符
_: 代表1位长度的任意字符
like: 在执行模糊查询时,必须使用like来作为匹配条件
-- 带where条件的查询 -- 模糊查询(某个字段, 包含关键字)
-- 语法: select * from 表名 where 字段 like '%关键字%'
-- 查询名字中带有李的
-- select * from student where username like '%李%'
-- 查询名字的最后一个字是祥的
-- select * from student where username like '%祥'
select max(age) from student
select min(age) from student
select avg(age) from student
select sum(age) from student
select count(*) cc from student
-- 统计查询(最大值、最小值、平均值、总和、总记录数)
-- 查询最大的年龄
-- select max(age) from student
-- 查询最小的年龄
-- select min(age) from student
-- 查询年龄的平均值
-- select avg(age) from student
-- 查询年龄的总和(所有人的年龄加到一起)
-- select sum(age) from student
-- 重点:查询总记录数(一共有多少条数据)
-- select count(*) from student
-- 可以为查询到的字段定义别名
-- select id,username from student
-- select id as abc, username as hello from student
-- select id abc, username hello from student
select count(*) total from student
order by 可以对查询结果按某个字段进行升序或者降序排列
可进行排序的字段通常是 整型 英文字符串型 日期型 (中文字符串也行,但一般不用)
-- 对查询结果进行排序
-- 语法:select * from student order by 字段 [asc/desc]
-- asc 默认就是 asc,表示升序(从小到大排序)
-- desc ,表示降序(从大到小排序)
-- 查询所有的学生,并按年龄升序排序
-- select * from student order by age
-- select * from student order by age asc
-- 查询所有的学生,按年龄降序排序
-- select * from student order by age desc
-- 查询所有的男同学,并按年龄降序排序
-- sql中,既有条件,又有排序,条件要写到前面,排序要写到后面
-- 条件是条件、排序是排序,之间没有任何关系,中间不要加and、or之类的
select * from student where sex='男' order by age desc
注意:如果SQL语句中,有where和order by,where一定要放到order by之前
limit 用来限制查询结果的起始点和长度
-- 限制查询结果(类似于截取查询结果)
-- 语法:select * from student limit 起始位置, 长度
-- 起始位置:从0开始,0表示第1条数据的位置。如果从0的位置截取,0可以省略
-- 长度:表示长度的数字
-- 查询所有学生中的第1、2、3个
-- select * from student limit 0, 3
-- select * from student limit 3
-- 查询所有学生中的第4、5、6个
-- select * from student limit 3, 3
-- 如果SQL中,有条件、有排序、有limit。那么顺序应该是
-- 先写条件、再写排序、最后写limit,并且每一部分之间用空格隔开即可
-- 查询年龄最大的学生的全部信息(id、name、age、sex)
-- select * from student order by age desc limit 1
-- 查询年龄最小的女同学的信息
select * from stu where sex='女' order by age asc limit 1
注意:where、order by、limit如果一起使用,是有顺序的,where在最前面、其次是order by、limit要放到最后。另外三者之间没有and之类的。
小结
select 字段 from 表名 [where 条件] [order by 排序字段 排序规则] [limit 起始位置,长度]
select count(*) as total from 表名 – 查询总记录数
格式:
update 表名 set 字段1=值1, 字段2=值2,... where 修改条件
修改表中的哪一条(几条)数据的 字段1=值1…
不指定修改条件会修改所有的数据
update student set age=20, sex='女' where id=11
update student set age=25, sex='女'
格式: delete from 表名 where 删除条件
注意:不指定条件将删除所有数据
-- 删除一条数据
delete from student where id=11
-- 删除满足条件的数据
delete from student where id>6
-- 没有指定条件,删除全部数据
delete from student
drop table stu; – 删除stu表
drop database 111_db – 删除库
小结
数据库名
上面 --> 右键 --> 运行SQL文件 --> 选择SQL文件,运行即可完成导入。student
上,右键 --> 转储SQL文件 --> 结构和数据,选择保存位置保存即可查询班级号为2的学生信息
SELECT s.name, s.age, s.id, s.class_id FROM student s JOIN classes c ON s.class_id = c.id WHERE c.id = 2
刚才是直接使用sql语句, 去操作数据库, 但是前端发起请求只能到达node层面的js代码, 所以应该让node编写代码, 链接mysql数据库, 并且执行预先编写好的mysql语句执行, 操作数据库
前端 <-> nodejs(express+mysql模块) <-> 数据库
mysql模块是一个第三方模块,专门用来操作MySQL数据库。 可以执行增删改查操作
# 如果前面没有安装过其他模块,需要先初始化npm init
npm i mysql
小故事
curd: 就代表数据库的增删改查
c: create 就是添加 (增)
u: update 就是修改 (改)
r: read 就是查询 (查)
d: delete 就是删除 (删)
在js代码中, mysql模块使用
加载 MySQL 模块
创建 MySQL 连接对象
连接 MySQL 服务器
执行SQL语句
关闭链接
// 1. 加载mysql模块
const mysql = require('mysql');
// 2. 创建连接对象(设置连接参数)
const conn = mysql.createConnection({
// 属性:值
host: 'localhost',
port: 3306,
user: 'root',
password: '',
database: 'yingxiong'
});
// 3. 连接到MySQL服务器
conn.connect();
// 4. 完成查询(增删改查)
/*
conn.query(SQL语句, [SQL中占位符的值], (err, result, fields) => {
err: 错误信息
result: 查询结果
fields: 当前查询过程中涉及到的字段信息,一般用不着
});
*/
// 5. 关闭连接,释放资源
conn.end();
// 执行sql语句
// let sql = `INSERT INTO student SET name='小可爱', age=18, sex='女', tel=13900202121`;
// conn.query(sql, (err, result, fields) => {
// if (err) console.log(err);
// else {
// console.log(result);
// console.log(fields);
// }
// });
// 带占位符的写法
// (1): 用?占个位置, 在真正执行的时候, 会被替换为具体的值
let sql = `INSERT INTO student SET name=?, age=?, sex=?, tel=?`;
// (2): 参数2数组里的每个值按照顺序, 替换到?对应的位置上
conn.query(sql, ['娜娜', 20, '女', 13900004000], (err, result, fields) => {
if (err) console.log(err);
else {
console.log(result);
console.log(fields);
}
});
// 插入的快捷方式
let userObj = {
name: "小米",
age: 20,
sex: "男",
tel: 13900203123
}
let sql = `INSERT INTO student SET ?`;
conn.query(sql, userObj, (err, results, fields) => {
if (err) console.log(err);
else {
console.log(results);
console.log(fields);
}
})
// 查询数据
// let sql = `SELECT * FROM student WHERE age > 18 ORDER BY id LIMIT 0, 2`;
// conn.query(sql, (err, result, fields) => {
// if (err) console.log(err);
// else {
// console.log(result);
// }
// });
// 带占位符
let sql = `SELECT * FROM student WHERE age > ? ORDER BY id LIMIT ?, ?`;
conn.query(sql, [18, 0, 2], (err, result, fields) => {
if (err) console.log(err);
else {
console.log(result);
}
});
// 修改数据
// let sql = `UPDATE student SET name='哈哈', age=10, sex='男', tel=12300201302 WHERE id = 1`;
// conn.query(sql, (err, result, fields) => {
// if (err) console.log(err);
// else {
// console.log(result);
// }
// });
// 带占位符
let sql = `UPDATE student SET name=?, age=?, sex=?, tel=? WHERE id = ?`;
conn.query(sql, ['改后名字', 18, '男', 19020203030, 1], (err, result, fields) => {
if (err) console.log(err);
else {
console.log(result);
}
});
// 快捷更新方式
let obj = {
name: "改后的名字",
age: 18,
sex: "男",
tel: 13900201010,
id: 1
}
let sql = `UPDATE student SET ? WHERE id = ?`;
conn.query(sql, [obj, obj.id], (err, result, fields) => {
if (err) console.log(err);
else {
if (result.affectedRows > 0) { // 改变的条数大于0, 证明有数据被修改了
console.log("数据修改成功");
} else {
console.log("修改失败-可能数据不存在");
}
}
});
强调
对于增删改语句,返回的result是一个表示SQL执行结果的对象。其主要属性如下:
// 删除数据
// let sql = `DELETE FROM student WHERE id = 7`;
// conn.query(sql, (err, result, fields) => {
// if (err) console.log(err);
// else {
// console.log(result);
// }
// });
// 带占位符
let sql = `DELETE FROM student WHERE id = ?`;
conn.query(sql, [6], (err, result, fields) => {
if (err) console.log(err);
else {
if (result.affectedRows > 0) {
console.log("删除成功");
} else {
console.log("删除失败, 可能数据不存在");
}
}
});
基本的增删改查小结
物理删除 - 使用delete的SQL语句, 会真正从表里(磁盘上)抹去这个数据 - 无法找回, 但是如果不小心用户删除了, 想要找回, 怎么办呢?
逻辑删除(也叫标记删除) - 就是用一个字段, 来表示这一条数据的状态, 字段名字随便起, 例如叫status, 0代表无效, 1代表还存在.
给数据表student, 再添加一个字段, 叫status, 控制学生是否还存在
// 标记占位符, 就是把那条数据的status改成0, 以后查询时, 只查数据为1的
// let sql = `UPDATE student SET ? WHERE id = ?`;
// conn.query(sql, [{status: 0}, 9], (err, result, fields) => {
// if (err) console.log(err);
// else {
// if (result.affectedRows > 0) {
// console.log("删除成功");
// } else {
// console.log("删除失败, 可能数据不存在");
// }
// }
// });
// 注释掉上面代码, 我们查询下所有 有效的数据
let sql = `SELECT * FROM student WHERE sex = ? and status = ?`;
conn.query(sql, ['男', 1], (err, result, fields) => {
if (err) console.log(err);
else {
console.log(result);
}
});
function theMySQL(sql, params, callback) {
const mysql = require('mysql');
const conn = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'root',
database: '121_db'
});
conn.connect();
// 完成增删改查
conn.query(sql, params, callback);
conn.end();
}
// 导出
module.exports = theMySQL;
如有不足,请多指教,
未完待续,持续更新!
大家一起进步!