SQL语句
- 数据库相关概念
- 数据查询语言(DQL)
- 基本查询
- 数据类型
- 条件查询
- 多表查询
- 子查询
- 数据操作语言(DML)
- 数据定义语言(DDL)
- 数据控制语言(DCL)
- MySQL数据库约束
- 视图
- 练习题
数据库相关概念
关系数据库:MySQL、Oracle、SQL Server
非关系型数据库:MongoDB、Redis
软件测试在什么时候会用到数据库的知识?
- 搭建测试环境
- 通用数据库操作功能的测试(增删改查)
- 快速创建测试数据,提高测试工作效率
- 性能测试时更便于理解系统结构
数据模型分类
- 层次模型(一对多)
- 网状模型(多对多)
- 关系模型(带有一些特殊属性的一张二维表,例如学生表)
关系型基本概念:关系(一张表)、元组(一行)、属性(一列)、主键(能唯一确定一个元组的某个属性组)。
数据查询语言(DQL)
SQL语句一般分为DQL、DML、DCL、DDL及功能函数。
在练习之前,先建立三张表
-- ----------------------------
-- Table structure for dept
-- ----------------------------
DROP TABLE IF EXISTS `dept`;
CREATE TABLE `dept` (
`deptno` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`dname` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`loc` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of dept
-- ----------------------------
INSERT INTO `dept` VALUES ('dept01', '技术部', '武汉');
INSERT INTO `dept` VALUES ('dept02', '销售部', '武汉');
INSERT INTO `dept` VALUES ('dept03', '客服部', '上海');
INSERT INTO `dept` VALUES ('dept04', '管理部', '成都');
INSERT INTO `dept` VALUES ('dept05', '技术支持', '武汉');
-- ----------------------------
-- Table structure for emp
-- ----------------------------
DROP TABLE IF EXISTS `emp`;
CREATE TABLE `emp` (
`empno` int(11) NULL DEFAULT NULL,
`ename` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`jobno` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`mgr` int(11) NULL DEFAULT NULL,
`hiredate` date NULL DEFAULT NULL,
`deptno` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of emp
-- ----------------------------
INSERT INTO `emp` VALUES (1001, '张三', 'j01', 1005, '2010-01-01', 'dept01');
INSERT INTO `emp` VALUES (1002, '李四', 'j02', 1005, '2011-12-02', 'dept01');
INSERT INTO `emp` VALUES (1003, '王二', 'j01', 1005, '2015-11-11', 'dept01');
INSERT INTO `emp` VALUES (1004, '李丽', 'j03', 1005, '2016-04-06', 'dept01');
INSERT INTO `emp` VALUES (1005, '韩梅', 'j04', 1013, '2014-03-07', 'dept01');
INSERT INTO `emp` VALUES (1006, '小白', 'j05', 1009, '2014-07-07', 'dept02');
INSERT INTO `emp` VALUES (1007, '小明', 'j05', 1009, '2015-08-09', 'dept02');
INSERT INTO `emp` VALUES (1008, '小红', 'j05', 1009, '2017-04-15', 'dept02');
INSERT INTO `emp` VALUES (1009, '小李', 'j06', 1013, '2014-05-30', 'dept02');
INSERT INTO `emp` VALUES (1010, '李俊', 'j07', 1012, '2014-05-12', 'dept03');
INSERT INTO `emp` VALUES (1011, '刘玲', 'j07', 1012, '2018-03-26', 'dept03');
INSERT INTO `emp` VALUES (1012, '王雪', 'j08', 1013, '2019-03-06', 'dept03');
INSERT INTO `emp` VALUES (1013, '吴总', 'j21', 1014, '2014-03-28', 'dept04');
INSERT INTO `emp` VALUES (1014, '刘总', 'j22', NULL, '2014-05-12', 'dept04');
INSERT INTO `emp` VALUES (1015, '大王', 'j23', 1014, '2020-05-12', 'dept03');
INSERT INTO `emp` VALUES (1016, '小王', 'j23', 1013, '2020-07-12', 'dept03');
-- ----------------------------
-- Table structure for job
-- ----------------------------
DROP TABLE IF EXISTS `job`;
CREATE TABLE `job` (
`jobno` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`jobname` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`sal` float(10, 2) NULL DEFAULT NULL
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of job
-- ----------------------------
INSERT INTO `job` VALUES ('j01', 'java开发', 14560.00);
INSERT INTO `job` VALUES ('j02', '软件测试', 12345.00);
INSERT INTO `job` VALUES ('j03', '前端开发', 12000.00);
INSERT INTO `job` VALUES ('j04', '项目经理', 18000.00);
INSERT INTO `job` VALUES ('j05', '销售员', 8000.00);
INSERT INTO `job` VALUES ('j06', '销售经理', 10050.00);
INSERT INTO `job` VALUES ('j07', '客服', 5000.00);
INSERT INTO `job` VALUES ('j08', '客服经理', 6666.00);
INSERT INTO `job` VALUES ('j21', '总经理', 88888.00);
INSERT INTO `job` VALUES ('j22', '董事长', 150000.00);
INSERT INTO `job` VALUES ('j23', '售后', 8888.00);
SET FOREIGN_KEY_CHECKS = 1;
基本查询
SELECT * FROM job;
SELECT jobno,sal FROM job;
SELECT jobno,sal,sal*2+100 as salnew FROM job; #取别名,或用空格替代as
SELECT DISTINCT jobno FROM emp; #去重
SELECT * FROM emp LIMIT 2,5; #去掉前两行,从下一行开始往后显示5条数据
数据类型
MySQL数据类型:
- 数值类型
- 字符串类型
- 日期和时间类型
条件查询
SELECT * FROM emp WHERE empno=1010;
SELECT * FROM emp WHERE empno>=1010;
SELECT * FROM emp WHERE empno<>1010; #不等于
SELECT * FROM emp WHERE empno BETWEEN 1008 and 1010;
SELECT * FROM emp WHERE empno IN(1009,1010,1011);
SELECT * FROM emp WHERE ename LIKE '李%'; #单个字符'_'
SELECT * FROM emp WHERE mgr IS NULL;
#逻辑运算符:AND、OR和NOT
SELECT * FROM emp WHERE not empno=1010;
SELECT * FROM job ORDER BY sal; #ORDER BY默认升序排列
SELECT * FROM job ORDER BY sal desc;
SELECT jobname, sal as 薪资 FROM job ORDER BY 薪资 desc;
SELECT * FROM job ORDER BY jobno DESC,sal ASC;
多表查询
字符函数:length(x)、replace(x,char1,char2)、substring(x,start,length)…
SELECT * from job WHERE LENGTH(jobname)<12; #汉字采用utf-8编码,一个汉字3个字节
SELECT * from job WHERE CHAR_LENGTH(jobname)<4;
SELECT jobname,REPLACE(jobname,'经理','主管') from job;
数字函数
返回x的y次方:POW(x,y)
返回绝对值:ABS(x)
…
控制流函数
SELECT ename,IF(ename='王二','狗子','') from emp; #还有IFNULL(v1,v2)函数
SELECT jobname,jobno,sal,(CASE jobname
WHEN '软件测试' THEN sal+1000
WHEN '客服' THEN sal+500
ELSE sal
END)as newsal FROM job;
外键:一个表中的外键是对另外一个表中主键的引用。
SELECT * FROM dept d,emp e WHERE d.deptno=e.deptno;
SELECT worker.ename,worker.mgr,'work for',manager.empno,manager.ename
FROM emp worker,emp manager WHERE worker.mgr=manager.empno;
#左外连接left outer join:以左表为基础,如果右表中不存在的数据,则以null补足
SELECT emp.empno,emp.ename,dept.deptno FROM dept LEFT JOIN emp ON emp.deptno=dept.deptno;
SELECT emp.empno,emp.ename,dept.deptno FROM dept RIGHT JOIN emp ON emp.deptno=dept.deptno;
练习
#1.查询dept01号部门的员工姓名、职位、工资、部门名称
SELECT e.ename,j.jobname,j.sal,d.dname
FROM emp e,dept d,job j
WHERE e.deptno=d.deptno AND e.jobno=j.jobno AND d.deptno='dept01';
#Q:j和d不需要连接吗?不需要,因为e和d连接之后就相当于一张表了
#2.查询员工姓名、部门号、部门名称,要求将没有员工的部门也显示出来
SELECT e.ename,d.deptno,d.dname
FROM dept d LEFT JOIN emp e
ON d.deptno=e.deptno;
#Q:左外连接中的两表交换位置就相当于右外连接吗?对
SELECT语法顺序:
WHERE
GROUP BY
HAVING (对行分组的结果进行过滤)
ORDER BY
子查询
常用分组函数:AVG SUM COUNT MAX MIN
#group by子句
SELECT e.deptno,j.jobname,sum(j.sal)
FROM emp e,job j
WHERE e.jobno=j.jobno
GROUP BY e.deptno,j.jobname;
#having子句
SELECT e.deptno,ROUND(avg(j.sal),2) as '平均薪资'
FROM emp e,job j
WHERE e.jobno=j.jobno
GROUP BY e.deptno
HAVING avg(j.sal)>10000;
#like用于单个模糊查询,in用于多个具体查询
SELECT j.jobname,ROUND(AVG(j.sal),2)
FROM job j
WHERE j.jobname LIKE('%经理') or j.jobname IN('java开发','软件测试')
GROUP BY j.jobname
HAVING AVG(j.sal)>10000;
#嵌套查询
SELECT e.ename,j.sal
FROM emp e,job j
WHERE e.jobno=j.jobno AND sal<
(SELECT sal FROM job WHERE jobname='软件测试');
#先查询部门号为20的部门的最小工资,设为A,按部门号对部门进行分组,找出每个部门的最小工资,并且这个最小工资要大于A
SELECT e.deptno,MIN(j.sal)
FROM emp e,job j
WHERE e.jobno=j.jobno
GROUP BY e.deptno
HAVING MIN(sal)>
(SELECT MIN(sal)
FROM emp
WHERE deptno=20);
SELECT ename,deptno
FROM emp
WHERE deptno IN
(SELECT deptno
FROM emp
WHERE ename='王二' or ename='李俊');
#<ANY指小于最大值 >ANY指大于最小值
SELECT empno,ename,jobname
FROM emp,job
WHERE emp.jobno=job.jobno AND sal>ANY
(SELECT sal
FROM job
WHERE jobname='java开发')
AND jobname<>'java开发';
#>ALL 指大于最大值 <ALL指小于最小值
数据操作语言(DML)
INSERT UPDATE DELETE
数据定义语言(DDL)
CREATE ALTER DROP
数据控制语言(DCL)
GRANT REVOKE
MySQL数据库约束
- NOT NULL
- UNIQUE KEY
- PRIMARY KEY
- FOREIGN KEY
- DEFAULT
视图
视图是一张虚拟表,其本质对应于一条select语句,结果集被赋予一个名字,即视图名字。
练习题
sql文件
-- ----------------------------
-- Table structure for product
-- ----------------------------
DROP TABLE IF EXISTS `product`;
CREATE TABLE `product` (
`pro_id` int(11) NOT NULL,
`pro_name` varchar(14) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`pro_sup_id` int(11) NULL DEFAULT NULL,
`pro_num` int(11) NULL DEFAULT NULL,
`pro_price` float(7, 2) NULL DEFAULT NULL,
PRIMARY KEY (`pro_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of product
-- ----------------------------
INSERT INTO `product` VALUES (1001, 'iPhone6 Plus', 10, 120, 6000.00);
INSERT INTO `product` VALUES (1002, 'iPhone6', 10, 120, 5000.00);
INSERT INTO `product` VALUES (1003, 'mate7', 20, 100, 4500.00);
INSERT INTO `product` VALUES (1004, '荣耀6 Plus', 20, 200, 1999.00);
INSERT INTO `product` VALUES (1005, '小米 NOTE', 30, 50, 1900.00);
INSERT INTO `product` VALUES (1006, '荣耀6', 20, 150, 1499.00);
INSERT INTO `product` VALUES (1007, 'iPhone5S', 10, 150, 3500.00);
INSERT INTO `product` VALUES (1008, '小米4', 30, 100, 1499.00);
INSERT INTO `product` VALUES (1009, 'MX4', 40, 50, 1699.00);
INSERT INTO `product` VALUES (1010, 'MX4 PRO', 40, 120, 2199.00);
-- ----------------------------
-- Table structure for salegrade
-- ----------------------------
DROP TABLE IF EXISTS `salegrade`;
CREATE TABLE `salegrade` (
`sm_id` bigint(20) NULL DEFAULT NULL,
`pro_id` int(11) NULL DEFAULT NULL,
`sg_date` date NULL DEFAULT NULL,
`sg_grade` bigint(20) NULL DEFAULT NULL
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of salegrade
-- ----------------------------
INSERT INTO `salegrade` VALUES (20151051, 1001, '2015-01-16', 60000);
INSERT INTO `salegrade` VALUES (20151051, 1002, '2015-01-16', 30000);
INSERT INTO `salegrade` VALUES (20151038, 1003, '2015-01-16', 13500);
INSERT INTO `salegrade` VALUES (20151038, 1004, '2015-01-16', 19990);
INSERT INTO `salegrade` VALUES (20151038, 1006, '2015-01-16', 2998);
INSERT INTO `salegrade` VALUES (20151030, 1005, '2015-01-16', 1900);
INSERT INTO `salegrade` VALUES (20151030, 1008, '2015-01-16', 8994);
INSERT INTO `salegrade` VALUES (20151041, 1001, '2015-01-16', 72000);
INSERT INTO `salegrade` VALUES (20151041, 1007, '2015-01-16', 70000);
INSERT INTO `salegrade` VALUES (20151041, 1002, '2015-01-16', 10000);
INSERT INTO `salegrade` VALUES (20151035, 1009, '2015-01-16', 11893);
INSERT INTO `salegrade` VALUES (20151051, 1001, '2015-01-16', 60000);
INSERT INTO `salegrade` VALUES (20151051, 1001, '2015-01-16', 60000);
INSERT INTO `salegrade` VALUES (20151051, 1002, '2015-01-16', 30000);
INSERT INTO `salegrade` VALUES (20151038, 1003, '2015-01-16', 13500);
INSERT INTO `salegrade` VALUES (20151038, 1004, '2015-01-16', 19990);
INSERT INTO `salegrade` VALUES (20151038, 1006, '2015-01-16', 2998);
INSERT INTO `salegrade` VALUES (20151030, 1005, '2015-01-16', 1900);
INSERT INTO `salegrade` VALUES (20151030, 1008, '2015-01-16', 8994);
INSERT INTO `salegrade` VALUES (20151041, 1001, '2015-01-16', 72000);
INSERT INTO `salegrade` VALUES (20151041, 1007, '2015-01-16', 70000);
INSERT INTO `salegrade` VALUES (20151041, 1002, '2015-01-16', 10000);
INSERT INTO `salegrade` VALUES (20151035, 1009, '2015-01-16', 11893);
-- ----------------------------
-- Table structure for salesman
-- ----------------------------
DROP TABLE IF EXISTS `salesman`;
CREATE TABLE `salesman` (
`sm_id` bigint(20) NOT NULL,
`sm_name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`sm_job` varchar(14) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`sm_mgr` bigint(20) NULL DEFAULT NULL,
`sm_sex` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`sm_phno` bigint(20) NULL DEFAULT NULL,
PRIMARY KEY (`sm_id`) USING BTREE,
UNIQUE INDEX `uk_sm_phno`(`sm_phno`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of salesman
-- ----------------------------
INSERT INTO `salesman` VALUES (20141001, 'MILLER', 'DIRECTOR', NULL, 'M', 17745678923);
INSERT INTO `salesman` VALUES (20141030, 'JONES', 'MANAGER', 20141001, 'M', 13612345678);
INSERT INTO `salesman` VALUES (20151011, 'VICKY', 'SALESMAN', 20141031, 'F', 15812345678);
INSERT INTO `salesman` VALUES (20151030, 'JACK', 'SALESMAN', NULL, 'M', 17745678927);
INSERT INTO `salesman` VALUES (20151035, 'SWIFT', 'MANAGER', 20141001, 'M', 13912345678);
INSERT INTO `salesman` VALUES (20151038, 'SCOTT', 'SALESMAN', 20141030, 'F', 13512345678);
INSERT INTO `salesman` VALUES (20151051, 'SMITH', 'SALESMAN', 20141030, 'M', NULL);
-- ----------------------------
-- Table structure for supplier
-- ----------------------------
DROP TABLE IF EXISTS `supplier`;
CREATE TABLE `supplier` (
`sup_id` int(11) NOT NULL,
`sup_name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`sup_loc` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`sup_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of supplier
-- ----------------------------
INSERT INTO `supplier` VALUES (10, '苹果', '美国加利福尼亚');
INSERT INTO `supplier` VALUES (20, '华为', '广东深圳');
INSERT INTO `supplier` VALUES (30, '小米', '北京');
INSERT INTO `supplier` VALUES (40, '魅族', '广东珠海');
INSERT INTO `supplier` VALUES (50, 'vivo', '四川成都');
INSERT INTO `supplier` VALUES (60, '联想', '北京');
INSERT INTO `supplier` VALUES (70, 'HTC', '台湾桃源');
SET FOREIGN_KEY_CHECKS = 1;
习题
#1.查询product表,显示销售价格低于4000的商品信息
SELECT *
FROM product
WHERE pro_price<4000;
#2.查询product表,显示销售价格最高的商品信息
SELECT *
FROM product
WHERE pro_price=
(SELECT MAX(pro_price )
FROM product);
#3.查询product表,显示10号供应商所提供的商品信息
SELECT *
FROM product
WHERE pro_sup_id=10;
#4.查询product表,显示10号供应商所提供的商品的平均销售价格
SELECT AVG(pro_price)
FROM product
WHERE pro_sup_id=10;
#5.查询product表,显示每个供应商所提供商品的平均价格,平均价格保留两位小数,按供应商编号降序排列
SELECT pro_sup_id,ROUND(AVG(pro_price),2)
FROM product
GROUP BY pro_sup_id
ORDER BY pro_sup_id DESC;
#6.查询supplier表,显示在广东的供应商信息
SELECT *
FROM supplier
WHERE sup_loc LIKE '广东%';
#7.查询salesman表,显示领导编号为空的销售人员信息
SELECT *
FROM salesman
WHERE sm_mgr IS NULL;
#8.查询product表和supplier表,显示‘mate7’的供应商信息
SELECT *
FROM supplier
WHERE sup_id=(
SELECT pro_sup_id
FROM product
WHERE pro_name='mate7');
#9.查询salesman表,显示每个销售人员及其领导的姓名
SELECT a.sm_name,b.sm_name
FROM salesman a
LEFT JOIN salesman b
ON a.sm_mgr=b.sm_id;SELECT a.sm_name,b.sm_name
FROM salesman a
LEFT JOIN salesman b
ON a.sm_mgr=b.sm_id;
#10.查询salegrade表,显示2015年1月16日的销售总额
SELECT SUM(sg_grade)
FROM salegrade
WHERE sg_date='2015-1-16';
#11.查询salegrade表,显示2015年1月16日的销售最高的销售人员信息
SELECT *
FROM salesman
WHERE sm_id in (
SELECT sm_id
FROM salegrade
WHERE sg_grade=(
SELECT MAX(sg_grade)
FROM salegrade)
);
#12.查询salegrade表,显示2015年1月16日’iPhone6‘的销售数量
SELECT DISTINCT p.pro_num
FROM product p,salegrade s
WHERE p.pro_id=s.pro_id AND s.sg_date='2015-01-16' AND p.pro_name='iPhone6';
#13.查询salegrade表和salesman表,显示’SMITH‘在2015年1月的销售总额
SELECT SUM(sg_grade)
FROM salegrade sg,salesman sm
WHERE sg.sm_id=sm.sm_id AND sm.sm_name='SMITH' AND sg.sg_date LIKE '2015-01-%';
#14.查询product表和supplier表,显示每家供应商的名称,提供的商品数量,未提供商品的供应商也需要显示(显示数量为0)
SELECT sup_name,SUM(pro_num)
FROM supplier s,product p
WHERE s.sup_id=p.pro_sup_id
GROUP BY sup_id;
#15.查询salegrade,product表,显示2015年1月16日各型号商品的销售数量
SELECT DISTINCT SUM(pro_num)
FROM salegrade,product
WHERE salegrade.pro_id=product.pro_id AND
salegrade.sg_date='2015-1-16'
GROUP BY salegrade.pro_id;