昨天 Poppy 问我是不是应该学一些网页开发的东西, 我的回答是这样的:

今天花了点时间汇总了一些 MySQL 简单的命令.

======== 正文分割线 ========

有哪些常见的数据库:

  1. Oracle
  2. MySQL
  3. SQL Server
  4. MongoDB
  5. Redis
  6. Hadoop

以下所有命令基于数据库 kis_blog 编写, 可以通过 Navicat 或者 DataGrip 亲自体验一下.

注:

  1. poppython.com 的数据库采用的是阿里云的 RDS 云数据库(MySQL);
  2. Navicat 和 DataGrip 是 MySQL 的 GUI 客户端;
  3. MySQL 搭建完毕以后可以创建多个数据库, 每个数据库可以创建多张数据表;
  4. 警号 # 开头的是注释;
  5. 分号 ; 结尾代表语句结束;
  6. 本文由简入繁的顺序编写, 建议从头阅读, 不要跳过;

blogs 表结构

kis_blog 有 5 张表, 分别是:

  1. users: 用户表
  2. categories: 分类表
  3. comments: 评论表
  4. tags: 标签表
  5. blogs: 文章表

MySQL 的数据表类似于 Excel, 下边是表 blogs 的 Excel 描述:

上图中蓝色的文字是列, 橙色的文字是列的注释, 黑色的文字是数据, 每一行代表一条数据.

以下章节按照 crud boy 的顺序编写:

CURD 代表 CREATE(创建)、RETRIEVE(检索)、UPDATE(更新)、DELETE(删除) 几个单词的首字母

查询数据使用 SELECT 关键字:

# 查 blogs 的所有列
SELECT * FROM blogs; # MySQL 的关键字不区分大小写, 下面两条语句是等价的(建议使用大写):
SELECT * FROM blogs;
select * from blogs; # 查 blogs 的单个列
SELECT id FROM blogs; # 查 blogs 的多个列
SELECT id, title FROM blogs; # 去重
SELECT DISTINCT category_id FROM blogs;

排序使用 ORDER BY 关键字:

# 按照 id 排序(默认升序)
SELECT * FROM blogs ORDER BY id; # 按照 id 升序
SELECT * FROM blogs ORDER BY id ASC; # 按照 id 降序
SELECT * FROM blogs ORDER BY id DESC; # 按照 id, category_id 多个列排序(默认升序)
SELECT * FROM blogs ORDER BY user_id, category_id; # 按照 id, category_id 多个列排序(指定排序方向)
# ASC 和 DESC 只能影响到其前面的列
SELECT * FROM blogs ORDER BY user_id ASC, category_id DESC;

过滤数据使用 WHERE 关键字:

# 只看 poppy(你的 id 是 2 ) 发布的文章
SELECT * FROM blogs WHERE user_id = 2; # 只看置顶状态的文章
# status 列存储了一个字符串有以下可选值: DRAFT(草稿)、已发布(PUBLISHED)、TOP(置顶)、HIDE(隐藏)
SELECT * FROM blogs WHERE status = 'PUBLISHED'; # 只看 id 大于 10 的文章
SELECT * FROM blogs WHERE id > 10; # 只看 id 小于等于 2 的文章
SELECT * FROM blogs WHERE id <= 2; # 只看 id 位于 2 和 10 之间的文章 (包括 2 也包括 10)
SELECT * FROM blogs WHERE id BETWEEN 2 AND 10; # 只看 id 不等于 6 的文章, 以下两条语句是等价的
SELECT * FROM blogs WHERE id <> 6;
SELECT * FROM blogs WHERE id != 6;

过滤数据除了 WHERE 关键字之外, 还有 ANDORINNOT 等子句可以使用:

# 查看 user_id 为 1 并且 category_id 为 2 的文章
SELECT * FROM blogs WHERE user_id = 1 AND category_id = 2; # 查看 category_id 为 2 或者 category_id 为 3 的文章
SELECT * FROM blogs WHERE category_id = 2 OR category_id = 3; # 猜猜这行什么意思?
SELECT * FROM blogs WHERE (category_id = 2 OR category_id = 3) AND user_id = 1; # 查看 category_id 为 2 或者 category_id 为 3 的文章
SELECT * FROM blogs WHERE category_id IN (2, 3); # 只看 summary 为空的文章
SELECT * FROM blogs WHERE summary IS NULL; # 只看 summary 不为空的文章
SELECT * FROM blogs WHERE summary IS NOT NULL;

在一些后台系统中, 经常需要分页查询数据, 假如前端传递 /api/blogs?current=2&size=10 表示页码为 2, 页长为 10, 后端需要做以下处理:

# 查询第 2*10 条数据之后的 10 条数据, 也就是第 21 条到第 30 条
SELECT * FROM blogs LIMIT 2 * 10, 10; # 查询所有数据作为 count, 后端需要返回 current, size, count 三个字段给前端
# 用于发起下一次分页查询
SELECT COUNT(id) FROM blogs;

以上查询数据的方式都是通过精确匹配, MySQL 同样支持模糊匹配.

通配查询使用 LIKE 关键字, 最常用的通配符的 %, % 表示任意字符出现任意次数.

# 查看 title 中以 Git 开头的文章
SELECT * FROM blogs WHERE title LIKE 'Git%'; # 查看 title 中以 Git 结尾的文章
SELECT * FROM blogs WHERE title LIKE '%Git'; # 查看 title 包含 Git
SELECT * FROM blogs WHERE title LIKE '%Git%';

通过以上查询方式得到的数据就像 excel 里的行, 还可以做简单的拼接、计算:

# 给标题加上书名号
# CONCAT 函数表示将参数拼接在一起
# AS 关键字表示给拼接后的列取个新名字叫 full_title
SELECT CONCAT('《', title, '》') AS full_title FROM blogs; # 去掉 title 的首空格
SELECT LTRIM(title) FROM blogs; # 去掉 title 的尾空格
SELECT LTRIM(title) FROM blogs; # 去掉 title 的首尾空格
SELECT TRIM(title) FROM blogs; # 计算点赞率 (点赞率 = 点赞数 / 浏览数)
SELECT like_count / read_count AS like_rate FROM blogs;

MySQL 还支持以下函数:

  1. 文本处理类:

    • LEFT(): 返回字符串左边的字符
    • LENGTH(): 返回字符串的长度
    • LOWER(): 将字符串转换为小写
    • LTRIM(): 去掉字符串左边的空格
    • RIGHT(): 返回字符串右边的字符
    • RTRIM(): 去掉字符串右边的空格
    • SOUNDEX(): 返回字符串的SOUNDEX值
    • UPPER(): 将字符串转换为大写
  2. 日期处理类:
    • YEAR(): 获取年
    • MOUNTH(): 获取月
    • DAY(): 获取日
    • NOW(): 获取当前日期
    • 还有其他很多函数...
  3. 数值处理类:
    • AVT(): 返回某列的平均值
    • COUNT(): 返回某列的行数
    • MAX(): 返回某列的最大值
    • MIN(): 返回某列的最小值
    • SUM(): 返回某列值之和
    • ABS(): 返回一个数的绝对值
    • COS(): 返回一个角度的余弦
    • EXP(): 返回一个数的指数值
    • PI(): 返回圆周率
    • SIN(): 返回一个角度的正弦
    • SQRT(): 返回一个数的平方根
    • TAN(): 返回一个角度的正切
    • 还有其他很多函数...

除了上述的各种单表查询方法外, MySQL 还支持各种姿势的联表查询 (SQL 最强大功能之一):

  1. INNER JOIN(内联接)
  2. OUTER JOIN(外联接)
    • LEFT JOIN(左联接)
    • LEFT OUTER JOIN(左外联接)
    • RIGHT JOIN(右联接)
    • RIGHT OUTER JOIN(右外联接)
    • FULL JOIN(全连接)
    • FULL OUTER JOIN(全外联接)
  3. 交叉联接

这部分内容略多, 可以参考 Mysql表连接查询.

创建数据库:

# 创建数据库
# 这行语句比较复杂, 可以简单这样理解:
# 1. 如果 kis_blog 已存在的话则跳过
# 2. 如果 kis_blog 不存在则创建, 创建时:
# + 指定字符集为 utf8
# + 指定字符序为 utf8_general_ci
CREATE DATABASE IF NOT EXISTS kis_blog DEFAULT CHARSET utf8 COLLATE utf8_general_ci;

创建数据表 blogs:

CREATE TABLE IF NOT EXISTS `blogs`(
`id` INT UNSIGNED AUTO_INCREMENT,
`title` VARCHAR(100) NOT NULL,
`summary` VARCHAR(200),
`content ` VARCHAR(10000),
PRIMARY KEY ( `id` )
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

创建数据表的命令比较复杂, 以上仅定义了 id、title、summary、content 四个列.

数据表的每个列都有一个类型, MySQL 提供了很多可选的选项, 在实际开发中, 程序员需要按照真实的业务情况选择合适的数据类型, 简单来说分为以下几种:

  1. 字符串:

    • CHAR: 定长字符串
    • VARCHAR: 变长字符串
    • TINYTEXT: 短文本, 最多存储 255 个字符 (2^8-1)
    • TEXT: 长文本, 最多存储 65535 个字符 (2^16-1)
    • MEDIUMTEXT: 中等长度文本, 最多存储 16777215 个字符 (2^24-1)
    • LONGTEXT: 极大文本, 最多存储 4294967295 个字符 (2^32-1)
    • 其他二进制类型...
  2. 数字
    • TINYINT: 小整数, 0 - 255 之间
    • SMALLINT: 大整数, 0 - 65535 之间
    • MEDIUMINT: 大整数, 0 - 16777215 之间
    • INT: 大整数, 0 - 4294967295 之间
    • BIGINT: 极大整数
    • FLOAT: 单精度浮点数
    • DOUBLE: 双精度浮点数
    • DECIMAL: 小数
  3. 日期
    • DATE: 日期, 例如: 2013-07-20 (没错, 我们的纪念日)
    • TIME: 时间, 例如: 05:20:00
    • DATETIME: 混合 DATE 和 TIME, 例如: 2013-07-20 05:20:00
    • YEAR: 年, 例如: 2013
    • TIMESTAMP: 时间戳

除了数据类型外, 定义数据表还需要一些约束字段:

  1. AUTO_INCREMENT: 表明这个列是自增的, 常用于 id, 会从 1 开始, 每加一条数据就自动加 1 作为新增数据的id;
  2. NOT NULL: 表明这个列是必填的, 不能为空
  3. UNIQE: 表明这个列是唯一的
  4. PRIMARY KEY: 表明这个列是主键, 主键很重要

关于主键:

  1. 主键是一条记录的唯一表示, 就像公民的身份证号码;
  2. 主键字段必须唯一并且非空;
  3. 一个表只能有一个主键;
  4. 主键可以包含一个字段或多个字段, 多个字段时称为 "联合主键";

关于外键:

  1. 外键用来表示两个表之间的关系;
  2. 一个表可以有多个外键;

poppython.com 的数据库里有以下场景:

有用户表 users 用来存储用户的信息, 另有文章表 blogs, 一个用户可以有多个文章, 这种情况下, usersorders 是一对多的关系.

此时可以将 users.id 字段作为 blogs 表的主键, users.id 就是 users 表的外键, users 通常被称为主表, blogs 被称为子表.

创建数据使用 INSERT 关键字:

# 创建一篇示例文章
INSERT INTO blogs (
user_id,
title,
category_id,
content,
pathname,
STATUS
)
VALUES (
2,
'示例标题',
7,
'示例文章',
'test-insert',
'DRAFT'
);

在实际的开发过程中, 数据表设计比较复杂, 需要尽可能的满足当前甚至未来的业务, 经常需要多个程序员共同商讨.

修改数据相对来说比较简单, 修改数据表使用 ALTER 关键字, 修改数据使用 UPDATE 关键字:

# 为 blogs 添加列
ALTER TABLE blogs ADD test_column CHAR(20); # 删除 blogs 的 test_column 列
ALTER TABLE blogs DROP COLUMN test_column; # 将 id 为 37 的文章状态改为 "置顶"
UPDATE status = 'TOP' FROM blogs WHERE id = 37; # 将所有文章的状态改为 "已发布"
UPDATE status = 'PUBLISHED' FROM blogs WHERE id > 0;

删数据也很简单, 删除数据库和数据表使用 DROP 关键字, 删除数据使用 DELETE 关键字:

# 删除数据库
DROP DATABASE db_name; # 删除数据表
DROP TABLE table_name; # 删除 id 为 42 的文章
DELETE FROM blogs WHERE id = 42;

其他

事务

在实际的开发中经常需要批量执行一些 SQL 语句, 并且这批 SQL 要么全部成功, 要么不执行, 这种情况下需要使用事务.

START TRANSACTION
# 批量的 SQL 语句...
COMMIT TRANSACTION

存储过程

在我的理解中, 存储过程相当于封装了 SQL 的函数.

TODO: 本王这部分的了解太浅, 暂时略过.

游标

TODO: 本王这部分的了解太浅, 暂时略过.

撤销

SQL 的 ROLLBACK 命令用来撤销 SQL 语句.

DELETE FROM table_name;
ROLLBACK;

索引

索引用来排序数据以加快搜索的速度, 索引分为:

  1. 普通索引
  2. 唯一索引
  3. 主键索引
# 创建普通索引
ALTER TABLE blogs ADD INDEX title; # 创建唯一索引
ALTER TABLE blogs ADD UNIQUE pathname; # 创建主键索引
ALTER TABLE blogs ADD PRIMARY KEY(id);

查看索引:

SHOW INDEX FROM blogs;

删除索引:

DROP INDEX title ON blogs;

ORM

从上边的原始 SQL 代码可以看到操作数据表是很复杂的, 在真实的业务中经常需要在 SQL 中需要注入变量后拼装出冗长的 SQL 语句.

ORM 解决了以上问题, ORM 是 Object Relational Mapping (对象关系映射)的简称, 可以简单理解成操作 SQL 的第三方工具包.

poppython.com 中使用了基于 Node 的 Sequelize 作为 ORM, 下面罗列了一些代码片段.

下面的代码用来创建文章, 在前端使用 POST 请求访问 /api/v1/blog 接口时, 会携带参数走到以下方法中:

async create() {
const { ctx, service } = this;
const { title, pathname, summary, tagIds, categoryId, content, status } = ctx.request.body;
const userId = ctx.helper.getLoggedIdByToken(ctx.cookies.get("tk"));
try {
const existed = await service.blog.findOne({ where: { pathname } });
if (existed) {
ctx.body = { success: false, message: ctx.__("ExistMsg", pathname) };
return;
}
const created = await service.blog.create({
title,
pathname,
summary,
userId,
categoryId,
content,
status,
});
const tags = await service.tag.findAll({ where: { id: tagIds } });
await created.setTags(tags);
ctx.body = { success: true, message: ctx.__("SuccessSmg"), data: created.id };
} catch (e) {
ctx.logger.error("Error while BlogController.create, stack: ", e);
ctx.body = { success: false, message: ctx.__("InnerErrorMsg") };
}
}

上边的代码只有常规的对象, 完全看不到原始 SQL 的影子.

MySQL 的优化

在庞大的业务数据下, MySQL 经常需要各种各样的优化方式, 比如:

  1. 使用缓存数据库
  2. 使用恰当的数据类型
  3. 创建高性能的索引
  4. 优化查询语句
  5. 读写分离
  6. 分布式数据库
  7. ...
  8. 这方面我是半桶水, 就不晃荡了...

开发一个创建文章的功能的流程

第一步: 在后端定义了一些路由地址, 比如:

// 当用于访问 /admin/write.html 时, 返回一个静态的页面
router.get("/admin/write.html", controller.view.admin.renderWrite); // 当收到 /api/v1/blog 的POST 请求时, 执行 `controller.api.blog` 控制器的 `create` 方法
router.post("/api/v1/blog", controller.api.blog.create);

第二步: 前端创建 write.html, 下面是伪代码:

<form id="js_writeForm" action="#">
<input type="text" name="title" placeholder="请输入标题" />
<textarea name="content" placeholder="请输入正文"></textarea>
<button type="submit">提交</button>
</form> <script>
$(document).ready(function () {
var $writeForm = $("#js_writeForm"); // 监听表单的提交事件
$writeForm.on("submit", function (event) {
// 阻止默认的提交事件
evt.preventDefault(); // 获取表单数据
var writeFormData = $writeForm.serializeJSON(); // 发起网络请求
$.ajax({
type: "POST",
url: "/api/v1/blog",
// 在请求结束后执行一些逻辑
success: function (res) {
if (res.success) {
alert("操作成功");
} else {
alert("操作失败");
}
}
});
});
});
</script>

第三步: 后端处理前端提交的 title, content 等数据, 将数据存入数据表, 并将存储结果返回给前端;

第四步: 前端在收到后端的返回结果后, 执行对应的消息提示;

第五步: END;

======== 本文结束 ========

2020-10-14 更新

很开心这篇文章能帮助到别人~


如果你有问题欢迎留言和我交流, 阅读原文

写给 Poppy 的 MySQL 速查表的更多相关文章

  1. [功能集锦] 003 - 一键生成mysql数据字典/数据库速查表

    写在前面: 因为工作时候经常遇到半路接手项目的情况,由于年代久远,数据库字典这块经常缺失.故写此篇,以便复用,也希望对大家有点帮助. 随笔内容不高级,如有不妥,不吝指正. ps:有另一篇详细随笔可以参 ...

  2. java-Mysql-SQLServer数据类型匹配速查表

    java-Mysql-SQLServer数据类型匹配速查表 Mysql ************************************ 当前列 ClassName ColumnType Di ...

  3. python 下的数据结构与算法---2:大O符号与常用算法和数据结构的复杂度速查表

    目录: 一:大O记法 二:各函数高阶比较 三:常用算法和数据结构的复杂度速查表 四:常见的logn是怎么来的 一:大O记法 算法复杂度记法有很多种,其中最常用的就是Big O notation(大O记 ...

  4. Java, C#, Swift语法对比速查表

    原文:Java, C#, Swift语法对比速查表   Java 8 C# 6 Swift 变量 类型 变量名; 类型 变量名; var 变量名 : 类型; 变量(类型推断) N/A var 变量名= ...

  5. ABP问题速查表

    如果你领导要让你一夜之间掌握ABP,并且用ABP撸一个项目出来,你很可能很快速的过了一遍ABP文档就马上动手干活了.那么这篇文章就很适合你. 这篇文章列出了很多ABP新手问的问题和解答.注:有些同学问 ...

  6. 【转】shell速查表

    shell速查表 转自:https://www.jianshu.com/p/a98a334bfb25 1. 变量 #!/bin/bash msg="hello world" ech ...

  7. 【转】Vim速查表-帮你提高N倍效率

    Vim速查表-帮你提高N倍效率 转自:https://www.jianshu.com/p/6aa2e0e39f99 去年上半年开始全面使用linux进行开发和娱乐了,现在已经回不去windows了. ...

  8. GNU Emacs命令速查表

    GNU Emacs命令速查表 第一章  Emacs的基本概念 表1-1:Emacs编辑器的主模式 模式 功能 基本模式(fundamental mode) 默认模式,无特殊行为 文本模式(text m ...

  9. bash基本命令速查表

    来源:https://github.com/skywind3000/awesome-cheatsheets/blob/master/languages/bash.sh ################ ...

随机推荐

  1. nginx反向代理部署springboot项目报404无法加载静态资源

    问题:nginx反向代理部署springboot项目报404无法加载静态资源(css,js,jpg,png...) springboot默认启动端口为8080,如果需要通过域名(不加端口号)直接访问s ...

  2. flowable流程启动时监听器

    一.核心配置类 package com.magus.project.flow.config; import com.google.common.collect.Maps; import com.mag ...

  3. PP模块的组织架构

    组织架构的层次,从上而下依次是: (1),集团-->对应系统client级别,用户登录SAP系统时,每一个client就是对应一个集团:在数据库中,每一个client都对应一个唯一的标识. (2 ...

  4. 使用JMeter进行压力测试

    使用JMeter进行压力测试(基础篇) 1.启动Jmeter 双击图中所示文件出现如下图所示即启动成功 2 新建测试计划 File------>new 2.1右键新建线程组 add-----&g ...

  5. ubuntu虚拟机启用双网卡IP配置

    首先要登入自己的虚拟机,这里以ubuntu为例. 配置两块网卡,一块eth0为NAT模式,另一块为eth1仅主机模式 # 进入网卡配置页面vi /etc/network/interfaces # Th ...

  6. Vue 面试题总结

    1. Vue 框架的优点是什么? (1)轻量级框架:只关注视图层,大小只有几十Kb:     (2)简单易学:文档通顺清晰,语法简单:     (3)数据双向绑定,数据视图结构分离,仅需操作数据即可完 ...

  7. 史上最全的pycharm快捷键!快进来点个收藏吧

    Alt+Enter 自动添加包 Ctrl+t SVN更新 Ctrl+k SVN提交 [编辑类:](https://link.zhihu.com/?target=https://www.jianshu. ...

  8. 对接口报错404 发现url多了一些不可描述的代码%E2%80%8B

    接口url出现了空格,复制的url可能出现空格肉眼看不出来,手动输入一遍URL

  9. Npoi XWPF Word 导出时插入图片无法显示 bug 完美解决

    一.来自客户的需求 最近客户来个新需求生成一个word 标签纸,并且需要在标签纸上插入一个logo,并且将erp 中的数据取出来自动写在文档上,不由得淡淡一笑,这不难呀! 于是乎我就写下了这样的代码: ...

  10. 消息队列 ---常用的 MQ 中间件

    目前市面上比较常用的 MQ(Message Queue,消息队列)中间件有 RabbitMQ.Kafka.RocketMQ,如果是轻量级的消息队列可以使用 Redis 提供的消息队列,其中 Redis ...