数据库操作
数据库相关概念
仓库:存放货物 数据库:存放数据(账号、商品数据、交易数据、浏览商品的记录) 大数据(人工智能):从大量的存储的数据当中提取有价值的信息(用户画像) 数据需要进行存储,存储到专门的数据库中,方便管理数据
数据库介绍DBMS
数据库 (database) 是用来组织、存储和管理数据的仓库(DBA)
- 数据库常用操作:增删改查
- 新增
- 删除
- 修改
- 查询
- 数据库类型(关系数据库;非关系数据库)
- MySQL
- Oracle
- SQL Server
- 。。。。。。
- MongoDB
- Redis
总结:数据库需要有一个软件,有很多流行的数据库软件 我们的侧重点学习关系数据库:MySQL
MySQL介绍
MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Oracle 旗下产品
- 关系数据库的存储结构:以表(Excel)为单位进行数据存储
- 一行就是一条数据,一列称为一个字段
总结:理解MySQL的数据存储结构:一行就是一条数据,一列称为一个字段
安装配置数据库环境
- PHPStudy : 这是一个集成测试环境,环境中包括PHP、MySQL和web服务器(Apache/Nginx)
- 安装方式:双击安装包,一直下一步即可
- 需要再安装一个Navicat(可视化数据客户端,方便操作数据库)
- 安装注意事项:
- 用不到的软件先关闭,防止端口冲突
- 杀毒软件需要先停掉
数据库用法
- PHPStudy
- 双击一直下一步即可完成安装
- 如果端口有冲突,可以点击【配置】按钮进行修改
- 数据库的密码修改:【数据库】菜单
总结:可以修改端口;可以修改数据库的密码
基于Navicat操作数据库
- 创建一个数据库链接
- 创建数据库
- 创建表结构:点击【新建表】
- 向表中插入数据
总结
- 创建数据库链接(远程登录数据库)
- 创建一个新的数据库
- 创建存储数据的表结构
- 可以手动向表中添加数据
SQL基本用法
SQL(英文全称:Structured Query Language)是结构化查询语言,专门用来访问和处理数据库的编程语言。 SQL可以让你通过写代码方式操作数据库
- 三个关键点
- SQL 是一门数据库编程语言
- 使用 SQL 语言编写出来的代码,叫做 SQL 语句,可以用于操作数据库中的数据。
- SQL 语言只能在关系型数据库(例如 MySQL、Oracle、SQL Server)中使用。非关系型数据库(例如 Mongodb) 不支持 SQL 语言
- SQL能做什么
- 从数据库中查询数据
- 向数据库中插入新的数据
- 更新数据库中的数据
- 从数据库删除数据
- 可以创建新数据库
- 可在数据库中创建新表
- 可在数据库中创建存储过程、视图
- etc…
总结:SQL是一种编程语言,可以操作数据库(通过SQL进行数据的增删改查)
常用SQL语句
- SQL语句基本的增删改查操作
-- 查询
-- select 字段1,字段2... from 表名 where 字段名称=字段值 and/or 字段名称=字段值
-- select id, uname from myuser
-- select * from myuser
-- 插入数据
-- insert into 表名 (字段名称, 字段名称1,...) values (字段值,字段值1,...)
-- insert into myuser (uname, pwd) values ('lisi', '123')
-- 更新数据
-- update 表名 set 字段名称=字段值,.... where 字段名称=字段值 and/or 字段名称=字段值
-- update myuser set uname='spike', pwd='456' where id=3
-- 删除数据
-- delete from 表名 where 字段名称=字段值 and/or 字段名称=字段值
-- delete from myuser where id=3
总结:基于SQL语句的增删改查操作可以非常方便的对数据库中的数据进行批量操作。
通过程序操作数据库
通过程序操作数据:程序通过执行SQL语句操作数据库中的数据
程序操作数据库介绍
mysql模块是一个第三方模块,专门用来操作MySQL数据库。 可以执行增删改查操作。
# 如果前面没有安装过其他模块,需要先初始化
npm i mysql
- curd: 就代表数据库的增删改查
- c: create 就是添加 (增)
- u: update 就是修改 (改)
- r: read 就是查询 (查)
- d: delete 就是删除 (删)
操作数据库基本步骤
- 加载 MySQL 模块
- 创建 MySQL 连接对象
- 连接 MySQL 服务器
- 执行SQL语句
- 关闭链接
/*
基本的数据库操作
*/
// 1、导入mysql第三方包
const mysql = require('mysql')
// 2、准备连接数据库相关参数
const cn = mysql.createConnection({
// 数据库所在的电脑的IP地址或者域名
host: 'localhost',
// 数据库的端口
port: 3307,
// 数据库名称
database: 'mytest-db',
// 数据库账号
user: 'root',
// 数据库密码
password: 'admin123'
})
// 3、执行连接操作
cn.connect()
// 4、此时就可以对数据库进行操作了
cn.query('select * from users', function (err, result) {
console.log(result[0].username)
})
// 5、关闭数据库连接
cn.end()
总结:通过mysql第三方包可以操作数据库,本质上依然通过SQL语句操作数据库
封装通用的数据库操作方法
需求:数据库操作流程是固定的,增删改查只有SQL语句不同,所以可以封装通用函数操作数据库
// 1、导入mysql包
const mysql = require('mysql')
// 封装通用的数据库擦走函数
// 数据库操作实际上是异步
function opreateDb (sql, callback) {
// 2、创建数据库链接(准备参数)
const cn = mysql.createConnection({
// 数据库所在主机名称(域名或者IP地址)
host: 'localhost',
// 数据库服务的端口
port: 3307,
// 数据库名称
database: 'test128',
// 数据库账号
user: 'root',
// 操作数据库的密码
password: 'admin123'
})
// 3、执行链接数据库操作
cn.connect()
// 4、此时可以操作数据了
// const sql = 'select * from myuser'
cn.query(sql, function (err, result) {
// 如果err是null表示查询成功,否则表示错误提示
// result表示从数据库中查询出的结果
// console.log(result)
callback(result)
})
// 5、关闭链接
cn.end()
}
const sql = 'select * from myuser'
opreateDb(sql, function (ret) {
console.log(ret)
})
注意:
- 数据库的操作是异步的
- 异步的结果只能用回调函数获取,不可以使用返回值
回顾
- 服务器端开发(express中间件)
- 中间件是什么?对经过它的信息进行处理;对于浏览器请求来说,中间件用于处理前端传递的数据。
- 中间件类型:内置中间件;自定义中间件;第三方中间件
- 内置中间件:静态资源服务;处理post请求参数(把拦截到的参数添加到req.body属性中)
- 自定义中间件:a中间添加一个req.salt=’盐’,b中间件就可以得到req.salt(想让中间件进入下一个环节必须调用next方法)
- 第三方中间:处理跨域问题cors,cors本质就是后端设置响应头
- 返回json数据的用法:res.json()
- 数据库
- 数据库管理系统(软件),主要用于数据的管理(存储、查询、添加、修改、删除、安全控制。。。)
- SQLServer/MySQL/Oracle…;mongodb/redis…
- 熟悉关系数据库MySQL(以表为单位存储数据:表结构类似于Excel,分为行和列)
- 安装一个数据库软件:PHPStudy、Navicat
- 熟悉数据库的基本操作(通过图形界面方式操作数据库)
- 创建数据库链接
- 创建一个新的数据库
- 创建一张表
- 手动向表中添加数据
- 熟悉SQL语言的基本作用:用于批量操作数据库中的数据
- 基于SQL的增删改查语句
- insert
- update
- delete
- select
- 基于后端程序方式操作数据库(基于SQL语句操作数据库)
- 安装mysql包
- 导入mysql包
- 创建数据库链接
- 执行链接动作
- 操作数据
- 关闭链接
- 封装通用的操作数据库的方法
- 基于SQL的增删改查语句
基本的增删改查
基本的查询
执行查询类型的SQL语句,查询结果(result)是一个数组,数组的每个单元是对象,每个对象就是一条记录,对象的属性是数据表的字段名
function operateData (sql, callback) {
// 1、导入mysql第三方包
const mysql = require('mysql')
// 2、准备连接数据库相关参数
const cn = mysql.createConnection({
// 数据库所在的电脑的IP地址或者域名
host: 'localhost',
// 数据库的端口
port: 3307,
// 数据库名称
database: 'mydb',
// 数据库账号
user: 'root',
// 数据库密码
password: 'admin123'
})
// 3、执行连接操作
cn.connect()
// 4、此时就可以对数据库进行操作了
// let sql = 'select * from users where id = 10'
// let result = null
cn.query(sql, (err, result) => {
// result = result
callback(result)
})
// 5、关闭数据库连接
cn.end()
// return result
}
// let ret = operateData()
// console.log(ret)
// let sql = 'select * from users where id = 10'
// operateData(sql, (ret) => {
// console.log(ret)
// })
let sql = 'select uname from users'
operateData(sql, (ret) => {
console.log(ret)
})
执行增删改语句
要完成增删改操作,只需要将SQL语句换成增删改语句即可。
对于增删改语句,返回的result是一个表示SQL执行结果的对象。其主要属性如下:
- insertId 添加时有该属性,表示新增数据的id
- affectedRows 受影响行数,表示受影响的行数。增删改的时候都有该属性
- changRows 改变的行数,修改操作的时候,会有该属性
/*
测试增删改查操作
*/
const db = require('./db-common.js')
// 删除id是13的数据
let sql = 'delete from users where id = 10'
db.operateData(sql, (result) => {
// affectedRows 表示操作影响的行数
console.log(result.affectedRows)
})
// 插入一条新的数据
// let sql = 'insert into users (uname, age) values ("lisi", 12)'
// let sql = 'insert into users (uname) values ("zhangsan")'
// db.operateData(sql, (result) => {
// console.log(result.affectedRows)
// })
// 更新一条数据
let sql = 'update users set age = 15, uname = "zhaoliu" where id = 17'
db.operateData(sql, result => {
console.log(result.affectedRows)
})
总结:
- 基于封装好的通用方法操作数据库
- 仅仅需要传递不同的SQL即可,代码流程是通用的
- 数据库操作的结果有几种场景?2种
- 查询操作,返回的结果是数组(查询出的列表结果数据)
- 增删改操作,返回的结果是对象(关键属性是affectedRows表示受影响的行数)
占位符模式的增删改查
- SQL中的“?” 就是占位符。比如
select * from heroes where id > ?
insert into heroes set ?
update heroes set ? where id = ?
delete from heroes where id = ?
如何为占位符传值
当SQL语句中使用了占位符,则query方法需要使用参数2为这些占位符传递实际的值。并且不同的 “?” 需要的值格式也不同。具体要符合下面三种要求:
- SQL中有 1 个占位符,则query方法的第二个参数设置为一个值
- SQL中有 多 个占位符,则query方法的第二个参数设置为数组,数组中的值按顺序分别传递给每个占位符
- SQL中,如果
字段=值,字段=值...
使用 “?” 站位了,则需为这个 “?” 传递一个对象,形式如下:- 更新操作可以使用
- 插入操作也可以使用
let val = {
// 字段: 值
name: '压缩',
nickname: '疾风剑豪',
// 其他...
}
有占位符的增删改查
- 单个占位符
// 例子一:查询id小于3的英雄let sql = 'select * from heroes where id < ?';conn.query(sql, 3, (err, result) => { if (err) throw err; console.log(result);});
- 多个占位符
// 例子二:查询id小于3的女英雄let sql = 'select * from heroes where id < ? and sex = ?';conn.query(sql, [3, '女'], (err, result) => { if (err) throw err; console.log(result);});
- 更多操作占位符
// 例子三:SQL中的 "字段=值, 字段=值..."的位置使用了一个占位符,则需为该占位符传递一个对象// 如果SQL语句中有 字段=值, 字段=值, .... 可以使用一个 ? 表示;并且要为这个问号传递一个对象let sql = 'insert into heroes set ?';let values = { // 字段: 值 name: '艾克', nickname: '时间刺客', age: 34};conn.query(sql, values, (err, result) => { if (err) throw err; // console.log(result); if (result.affectedRows > 0) { console.log('添加成功,最新添加的id为:' + result.insertId); } else { console.log('添加失败'); }});
- 带条件的更新操作占位符
// 例子四:// SQL中有两个占位符,所以要传递一个数组// 第1个问号表示 “字段=值, 字段=值...”,所以为这个问号传递一个对象let sql = 'update heroes set ? where id = ?';let values = { skill: '时光倒流', sex: '男'}conn.query(sql, [values, 36], (err, result) => { if (err) { console.log('修改失败'); } else { console.log('修改成功'); }});
总结:基于占位符方式分别进行增删改成操作
实现一个从数据库取数据的接口
const express = require('express')const path = require('path')const app = express() const db = require(path.join(__dirname, 'db-common.js'))app.listen(3000, () => { console.log('running...')})app.get('/users', (req, res) => { let sql = 'select * from myuser' db.operateDb(sql, null, (result) => { res.json(result) })})
总结:前端请求接口地址,后端监听客户端请求,根据请求去数据库查询结果,查到的数据返回即可。
分页
排序
数据库支持在查询数据时进行排序
-- order by 字段名称 asc/descselect * from myuser order by id asc-- 如果有查询条件,那么排序的规则写到最后select * from myuser where gender = 1 order by age asc
- asc表示升序排列(默认)
- desc表示降序排列
分页
分页:分多次查询数据,每次查询一部分数据 好处:查看方便;前端性能较高
-- limit 从第几条开始查询(从0开始), 每次查询几条select * from myuser order by id asc limit 1, 2
- 思考:从第几条开始和从第几页开始是一个意思吗?不是一个意思,但是有关系
- 从第几条开始用n表示
- 从第几页开始用pagenum表示
- 每页显示的条数用pagesize表示 | 第几页pagenum | 第几条n | 每页的条数pagesize | | —- | —- | —- | | 1 | 0 | 2 | | 2 | 2 | 2 | | 3 | 4 | 2 | | 4 | 6 | 2 | | 5 | 8 | 2 |
n = (pagenum - 1) * pagesize0 = (1 - 1) * 22 = (2 - 1) * 2
- 前端分页需要的参数是页码和每页的条数
- pagenum
- pagesize
app.get('/users', function (req, res) {
// 页码:第几页
const pagenum = req.query.pagenum
// 每页条数
const pagesize = req.query.pagesize
// 当前第几条
const n = (pagenum - 1) * pagesize
const sql = 'select * from myuser order by id limit ?, ?'
db.opreateDb(sql, [n, parseInt(pagesize)], function (ret) {
console.log(ret)
res.json(ret)
})
})
总结:前端分页一般会传递两个相关参数:页码和每页的条数,后端的第几条需要公式计算。