
“阅读本文大概需要25分钟。
你好,我是测试蔡坨坨。
对于测试同学来说,除了知道测试基础知识外,还需要掌握一些测试基本技能,主要有Linux、数据库、计算机网络等,在此之前我们已经讨论过Linux基础知识以及在实际工作中的应用,可参考往期文章「学会Linux,看完这篇就行了!」。
今天,我们就来聊一聊数据库,数据库是大学本科计算机系核心课程之一,其重要性不言而喻。
数据库在面试中基本属于必考内容,最多的就是手写SQL或口述SQL,面试官会给你出一个场景,比如班级、分数、课程之类的,一般考察表查询语句居多,例如多表查询、连接查询、子查询等。所以,当你准备转行踏入IT行业的时候,就首先需要掌握数据库。
本文主要科普作为一枚测试应该知道的数据库理论基础知识,知道这些不仅可以在面试时加分,而且可以加深你对数据库的理解,而不是仅仅停留在只会写几个SQL上面。
测试人员对于数据库理论知识的学习,肯定不需要像开发那么深入,但是一些基本的内容需要知道并掌握,简单来说,数据库基础,看完接下来的文章并搞明白就完全够用了。
当然,关于数据库进阶知识,比如数据库索引、事务、数据库三大范式、数据库调优、存储过程等内容也会在后续的文章中与大家讨论。
作为测试,数据库在日常工作中的权重占比还是比较大的,主要有以下几个应用场景:
and so on ……
以上,仅列举了一些日常工作中比较常见的场景,供大家参考。
紧接着,就来介绍一下数据库以及常用的SQL语句。
数据库的英文单词:Database ,简称DB。
数据库方向的岗位叫DBA(Database Administrat),也就是数据库管理员,专门和数据库打交道的,属于运维工程师的一个分支,主要负责业务数据库从设计、测试到部署交付的全生命周期管理。
数据库实际上就是一个文件集合,是一个存储数据的仓库,本质就是一个文件系统,数据库是按照特定的格式把数据存储起来,用户可以对存储的数据进行增删改查操作。
简单概括,数据库就是用于存储和管理数据的仓库。
具体来说,就是前端页面用户输入的数据通过接口传给后端,然后存储到数据库中,同时也支持从数据库中取数据传给前端页面做一个展示。
上面说了这么多数据库,而目前企业中使用最多的就是MySQL和Oracle数据库,后者因为是收费的,所以互联网公司尤其是中小型企业使用最多的就是MySQL数据库,其实数据库的学习其实和编程语言一样,当你熟练掌握其中一种时,其他的也就分分钟上手了。
因此,推荐初学者从MySQL数据库开始学习。


PS:Xshell或Xftp连接Linux服务器默认端口:22
Structured Query Language:结构化查询语言。
SQL是专门为数据库而建立的操作命令集,是一种功能齐全的数据库语言。在使用它时,只需要发出“做什么”命令,“怎么做”是不用使用者考虑的。
以上说了这么多数据库如何重要以及数据库是什么,那么应该如何自学呢?接下来就是干货来啦!
几个数据库相关的视频教程和两门价值几百的极客时间语音课,关注公众号:测试蔡坨坨,回复关键词:数据库,即可获取。学完这些基本的SQL语句理论知识就没什么问题了,接下来时间就是反复练习,达到能够熟练编写的程度就行了。
在哪里练习?想要练习数据库需要首先需要有数据的环境,有以下两种方法:

mysql -uroot -p密码
mysql -uroot -p(回车)
Enter password: (输入密码)

mysql -hip -P端口 -uroot -p

mysql --host=ip --user=root --password=密码


创建数据库命令
create database caituotuo;
create database caituotuo character set utf8;
create database caituotuo character set utf8 collate utf8_general_ci;
查看数据库命令
show databases;
show databases like '%tuotu%';
show create database caituotuo;
删除数据库命令
格式:drop database [数据库名称];
例如:
drop database caituotuo;
选中某个数据库
格式:use [数据库名称];
例如:
use caituotuo;
PS:这个命令可以不加分号。

类型 | 大小 | 用途 |
|---|---|---|
TINYINT | 1字节 | 小整数值 |
SMALLINT | 2字节 | 大整数值 |
MEDIUMINT | 3字节 | 大整数值 |
INT或INTEGER | 4字节 | 大整数值 |
BIGINT | 8字节 | 极大整数值 |
FLOAT | 4字节 | 单精度浮点数值 |
DOUBLE | 8字节 | 双精度浮点数值 |
DECIMAL | 对于DECIMAL(M,D),如果M>D则为M+2,否则为D+2 | 小数值 |
在计算机中,可以区分正负的类型,称为有符号类型。
无正负的类型,称为无符号类型。
简单的理解为就是,有符号值可以表示负数、0、正数,无符号值只能为0或者正数。
FLOAT(10,2):总长度为10,小数点后有2位。
DOUBLE和DECIMAL也类似。
超出范围会四舍五入。
' d''d'类型 |
|---|
DATE |
TIME |
YEAR |
DATETIME |
TIMESTAMP |
TIMESTAMP和DATETIME的异同:
创建表基础命令
-- 格式:
CREATE TABLE [表名] ([列名 1 ] [列类型],[列名 2 ] [列类型],[列名 3 ] [列类型] );
-- 例如:
CREATE TABLE STU (ID INT,NAME VARCHAR ( 20 );AGE INT );
注意:
约束条件
约束条件就是给列加一些约束,使该字段存储的值更加符合我们的预期。
约束条件 | 含义 |
|---|---|
UNSIGNED | 无符号,值从0开始,无负数 |
ZEROFILL | 零填充,当数据的显示长度不够的时候可以使用填补0的效果填充至指定长度,字段会自动添加UNSIGNED |
NOT NULL | 非空约束,表示该字段的值不能为空 |
DEFAULT | 表示如果插入数据时没有给该字段赋值,那么就使用默认值 |
PRIMARY KEY | 主键约束,表示唯一标识,不能为空,且一个表只能有一个主键 |
AUTO_INCREMENT | 自增长,只能用于数值列,默认起始值从1开始,每次增长1 |
UNITQUE KEY | 唯一值,表示该字段下的值不能重复,可以为空,可以有多个 |
COMMENT | 描述 |
注意:
如果一列同时有UNSIGNED、ZEROFILL、NOT NULL这几个约束,UNSIGNED、ZEROFILL必须在NOT NULL前面,否则会报错。
例子:
create table user_info_tab(
user_id int not null auto_increment,
user_name char(10),
password varchar(10),
user_nick varchar(10),
card_num bigint,
primary key(user_id)
);
显示当前数据库中所有表的名字
格式:
show tables;
显示某张表每一列的属性(列名、数据类型、约束)
格式:desc [数据表名称];
例如:
desc user_info_tab;
格式:drop table [数据表名称];
例如:
drop table cai;
向数据表中添加一列
格式:ALTER TABLE [数据表名称] ADD [列名] [列的数据格式] [约束];
例如:
ALTER TABLE user_info_tab ADD phone VARCHAR(11);
PS:
删除数据表的某一列
格式:ALTER TABLE [数据表名称] DROP [列名];
修改列的类型和名称
ALTER TABLE [表名] MODIFY [列名] [数据格式];(列名不变,其他要变)
ALTER TABLE [表名] CHANGE [旧列名] [新列名] [数据格式];(列名也要改变)
-- 插入数据
INSERT INTO user_info ( user_id, user_name, PASSWORD, user_nick, card_num )
VALUES
( 1, 'zhangsan', 'abc123', 'zhangsanfeng', 124567894651329785 ),
( 2, 'lisi', '122bbb', 'limochou', 124567894651324567 ),
( 3, 'wangwu', '123aaa', 'wangbaiwan', 214567894651324567 ),
( 4, 'liuqi', '12aaa', 'liuchuanfeng', 214563356651324567 ),
( 5, 'zhangliu', '12aaa', 'zhangwuji', 214563356658966567 );
语法:
drop和delete的区别:
语法:
update user_info set username = "poopoo" where userid = 1;
文末练习题中会给出查询语句相关示例。
SELECT product_name,weight FROM products_info ORDER BY weight DESC;
distinct:对某一列数据去重。
语句:select distinct 列名 from 表名; -- 显示此列不重复的数据
count:统计总行数。
MAX:最大值
MIN:最小值
AVG:平均值
SUM:求和
select max(列名) from 表名;
select min(列名) from 表名;
select avg(列名) from 表名;
select sum(列名) from 表名;
- 也可以跟where子句
limit
语法:
语法:GROUP BY
select sum(price), count(user_id), product_id from order_info_table group by product_id having count(user_id) > 2;
INNER JOIN(内连接):获取两个表中字段匹配关系的行的所有信息。
语法:SELECT * FROM [表名] a INNER JOIN [表名] b ON a.[列名] = b.[列名];
例如:
SELECT * FROM user_info_table a INNER JOIN order_info_table b ON a.user_id = b.user_id;
SELECT * FROM user_info_table a INNER JOIN order_info_table b ON a.user_id = b.user_id WHERE b.user_id IS NULL;
LEFT JOIN(左连接):以左表为基准,获取左表所有行的信息,即使右表没有对应匹配的行的信息。右表没有匹配的部分用NULL代替。
语法:SELECT * FROM [表名] a LEFT JOIN [表名] b ON a.[列名] = b.[列名];
SELECT * FROM products_info a LEFT JOIN suppliers_info b ON a.supplier_id = b.supplier_id;
RIGHT JOIN(右连接):与左连接相反,以右表为基准,用于获取右表所有记录,及时左表没有对应匹配的行的所有信息,左表没有匹配的部分用NULL代替。
语法:SELECT * FROM [表名] a RIGHT JOIN [表名] b ON a.[列名] = b.[列名];
SELECT * FROM products_info a RIGHT JOIN suppliers_info b ON a.supplier_id = b.supplier_id;
子查询(嵌套查询)
其他注意事项:数据库名和表名在Windows中是大小写不敏感的,但是在大多数类型的UNIX系统中大小写是敏感的。


一、创建如下要求的表格,并完成相应的题目。


-- 创建表
CREATE TABLE user_info (
user_id INT NOT NULL AUTO_INCREMENT,
user_name CHAR ( 10 ),
password VARCHAR ( 10 ),
user_nick VARCHAR ( 10 ),
card_num BIGINT,
PRIMARY KEY ( user_id )
);
-- 插入数据
INSERT INTO user_info ( user_id, user_name, PASSWORD, user_nick, card_num )
VALUES
( 1, 'zhangsan', 'abc123', 'zhangsanfeng', 124567894651329785 ),
( 2, 'lisi', '122bbb', 'limochou', 124567894651324567 ),
( 3, 'wangwu', '123aaa', 'wangbaiwan', 214567894651324567 ),
( 4, 'liuqi', '12aaa', 'liuchuanfeng', 214563356651324567 ),
( 5, 'zhangliu', '12aaa', 'zhangwuji', 214563356658966567 );
-- user_nick长度不够,修改user_nick的长度再重新插入数据
ALTER TABLE user_info MODIFY user_nick VARCHAR ( 20 );


-- 创建订单表
CREATE TABLE order_info (
order_id INT UNSIGNED ZEROFILL NOT NULL,
price DECIMAL ( 10, 2 ) NOT NULL,
order_status VARCHAR ( 30 ) NOT NULL,
product_id INT NOT NULL,
created datetime DEFAULT "2019-01-01 00:00:00",
user_id INT NOT NULL,
PRIMARY KEY ( order_id )
);
-- 插入数据
INSERT INTO order_info
VALUES
( 1, 4.99, 'pay', 1001, '2019-09-25 10:25:26', 1 ),
( 2, 9.99, 'nopay', 1002, '2019-09-26 10:25:26', 1 ),
( 3, 4.99, 'pay', 1001, '2019-09-25 10:25:26', 2 ),
( 4, 9.99, 'nopay', 1002, '2019-09-24 10:25:26', 2 ),
( 5, 19.99, 'pay', 1003, '2019-09-26 10:25:26', 2 ),
( 6, 4.99, 'pay', 1001, '2019-09-25 10:25:26', 3 ),
( 7, 4.99, 'pay', 1001, '2019-09-25 10:25:26', 4 ),
( 8, 9.99, 'pay', 1002, '2019-09-25 10:25:26', 4 ),
( 9, 19.99, 'pay', 1003, '2019-09-26 10:25:26', 4 ),
( 10, 29.99, 'pay', 1002, '2019-09-26 10:25:26', 6 );
-- where子句小练习
-- 1. 满足价格大于等于9的所有信息
SELECT * FROM order_info WHERE price >= 9;
-- 2. 查找满足product_id在1002和1003之间的
SELECT * FROM order_info WHERE product_id BETWEEN 1002 AND 1003;
-- 3. 查找user_id在1、3、5这三个数内的信息
SELECT * FROM order_info WHERE user_id IN (1,3,5);
-- 4. 查找订单状态是已支付的信息
SELECT * FROM order_info WHERE order_status = 'pay';
-- 5. 查找用户名类似于已li开头的信息
SELECT * FROM user_info WHERE user_name LIKE 'li%';
-- 6. 查找用户名中第二个字母是h的信息
SELECT * FROM user_info WHERE user_name LIKE '_h%';
-- 7. 查找用户名中第二个字母不是h的信息
SELECT * FROM user_info WHERE user_name NOT LIKE '_h%';
-- 8. 查找用户名中最后一个字母以i结尾的信息
SELECT * FROM user_info WHERE user_name LIKE '%i';
-- 9. 查找价格大于8,并且订单状态是已支付的所有信息
SELECT * FROM order_info WHERE price > 8 AND order_status = 'pay';
-- 10.查找用户表中user_nick为null的信息
SELECT * FROM user_info WHERE user_nick IS NULL;
-- 11.查找用户表中user_nick为 not null的信息
SELECT * FROM user_info WHERE user_nick IS NOT NULL;
-- 聚合函数练习
-- 1. 查找订单表中最大的价格,查找订单表中最小的价格
SELECT MAX(price),MIN(price) FROM order_info;
-- 2. 查找订单表中user_id=2的最小价格
SELECT MIN(price) FROM order_info WHERE user_id = 2;
-- 3. 分别列出订单表中user_id=2的最小价格和最大价格
SELECT MIN(price),MAX(price) FROM order_info WHERE user_id = 2;
-- 4. 分别列出订单表中user_id=2的最小价格和最大价格,并把最小价格的展示结果的列名改为"min_price"
SELECT MIN(price) AS min_price,MAX(price) FROM order_info WHERE user_id = 2;
-- 5. 求订单表的价格的平均值,求订单表中user_id=2的价格的平均值
SELECT AVG(price) FROM order_info;
SELECT AVG(price) FROM order_info WHERE user_id = 2;
-- 6. 分别列出订单表中user_id=2的价格的平均值、最小值、最大值
SELECT AVG(price),MIN(price),MAX(price) FROM order_info WHERE user_id = 2;
-- 7. 求订单表中user_id=1的价格的总和
SELECT SUM(price) FROM order_info WHERE user_id = 1;
-- 8. 求订单表中user_id=1或者user_id=3的价格总和
SELECT SUM(price) FROM order_info WHERE user_id = 1 OR user_id = 3;
-- 分组练习
-- 1.首先筛选状态为已支付的订单,然后按照user_id分组,分组后每一组对支付金额进行求和,最终展示user_id和对应组求和金额
SELECT user_id,SUM(price) FROM order_info WHERE order_status = 'pay' GROUP BY user_id;
-- 2.首先筛选状态为支付的订单,然后按照user_id分组,分组后每一组对支付金额进行求和,再过滤求和金额大于10的,最终展示user_id和对应组的求和金额
SELECT user_id,SUM(price) FROM order_info WHERE order_status = 'pay' GROUP BY user_id HAVING SUM(price) > 10;
-- 数据表连接查询和子查询练习
-- 1.查询订单表中的价格大于10元的用户的昵称(小提示:用户昵称在用户表中,订单价格在订单表中)
SELECT a.user_nick FROM user_info a INNER JOIN order_info b ON a.user_id = b.user_id WHERE b.price > 10;
SELECT user_nick FROM user_info WHERE user_id IN (SELECT user_id FROM order_info WHERE price > 10);
-- 2.查询用户名以l开头的用户买过的所有订单id和对应价格(小提示:订单id和对应价格在订单表中,用户名在用户表中)
SELECT o.order_id,o.price FROM order_info o WHERE o.user_id IN (SELECT user_id FROM user_info u WHERE u.user_name LIKE 'l%');
二、创建如下要求的表格,并完成相应的题目。


-- 1.按照表定义创建商品表+供应商表
-- 2.按照表数据插入所有数据
-- 创建商品表
CREATE TABLE products_info (
product_id INT UNSIGNED ZEROFILL NOT NULL,
product_name VARCHAR ( 30 ) DEFAULT 'water',
classification VARCHAR ( 30 ),
weight FLOAT ( 10, 2 ),
supplier_id INT,
PRIMARY KEY ( product_id )
);
-- 向商品表插入数据
INSERT INTO products_info
VALUES
( 1001, 'water', 'Daily_Necessities', 0.55, 1 ),
( 1002, 'soap', 'Daily_Necessities', 0.15, 2 ),
( 1003, 'paper', 'Daily_Necessities', 0.12, 3 ),
( 1004, 'pingpangqiu', 'sports', 0.05, 4 ),
( 1005, 'yumaoqiu', 'sports', 0.04, 6 );
-- 创建供应商表
CREATE TABLE suppliers_info (
supplier_id INT NOT NULL AUTO_INCREMENT,
supplier_name VARCHAR ( 30 ),
Registration_number INT,
contacts VARCHAR ( 30 ),
contacts_phone_num CHAR ( 11 ),
PRIMARY KEY ( supplier_id )
);
-- 向供应商表插入数据
INSERT INTO suppliers_info
VALUES
( 1, 'nongfushanquan', 1000001, 'mayun', '18026156362' ),
( 2, 'jiajieshi', 1000002, 'liuqiangdong', '13826156363' ),
( 3, 'qingfeng', 1000003, 'mahuateng', '18926156364' ),
( 4, '361du', 1000004, 'renzhenfei', '18226156365' ),
( 5, 'anta', 1000005, 'leijun', '18626156366' );
-- 3.修改供应商id为4的供应商名称为‘hongshuangxi’
UPDATE suppliers_info SET supplier_name = 'hongshuangxi' WHERE supplier_id = 4;
-- 4.查询商品重量大于0.10的商品的名称
SELECT product_name FROM products_info WHERE weight > 0.10;
-- 5.查询商品名称以字母p开头的商品的所有信息
SELECT * FROM products_info WHERE product_name like 'p%';
-- 6.查询商品重量大于0.10,小于0.20的商品名称
SELECT product_name FROM products_info WHERE weight > 0.10 AND weight < 0.20;
-- 7.按照商品分类统计各自的商品总个数,显示每个分类和其对应的商品总个数
SELECT classification,COUNT(classification) FROM products_info GROUP BY classification;
-- 8.将所有商品的名称按照商品重量由高到低显示
SELECT product_name,weight FROM products_info ORDER BY weight DESC;
-- 9.显示所有商品的信息,在右边显示有供应商的商品对应的供应商信息
SELECT * FROM products_info a LEFT JOIN suppliers_info b ON a.supplier_id = b.supplier_id;
-- 10.显示重量大于等于0.15的商品的供应商的联系人和手机号
SELECT s.contacts,s.contacts_phone_num FROM suppliers_info s INNER JOIN products_info p ON s.supplier_id = p.supplier_id and p.weight >= 0.15;
以上,完。
脚踏实地,仰望星空,和坨坨一起学习软件测试,升职加薪!