create database cgb2021 DEFAULT CHARACTER SET utf8; #创建数据库
#创建 数据库 库名 避免中文乱码(charset)
---------------------------------------------------
show databases; #查看数据库
#展示 所有数据库
---------------------------------------------------
drop database cgb2109; #删除库
#删除 数据库 库名
---------------------------------------------------
use cgb210901; #使用数据库
---------------------------------------------------
show tables;#查看所有的表
-------------------------------------------------------
create table tb_door(); #创建表
#创建 表 表名 (字段名称 字段类型(字段长度));
-------------------------------------------------------
drop table tb_door; #删除名称是 tb_door的表
-----------------------------------------------------
desc tb_door; #查看tb_door表结构
#描述 表名
------------------------------------------------------
alter table tb_room add column money NUMERIC(7,2); #添加列
#修改 表 表名 增加 列 列名 字段类型(长度,精确到几位)
----------------------------------------------------------
select 列名1,列名2 from 表名--查询表名中列名1和列名2的数据
select 列名 别名,列名2 别名 from 表名
select * from tb_order_detail; 查询tb_door表中的所有记录
查询 通配符/所有列 表名
SELECT * FROM emp; #查询所有列
SELECT ename FROM emp; #查名字列
SELECT empno,ename FROM emp;#查标号和名字
SELECT empno a FROM emp;#给列设置别名
--------------------------------------------------------------
insert into 表名 values(1,2,3,4);#向表中插入记录
#向表中插入数据 值们 给第一个字段赋值,
#注意:1.需要设置几个值?要看表里有几个字段
#2.值的顺序要和字段的顺序保持一致
#3.如果字段是字符串类型,设置值是必须要有“”‘’的标记。
----------------------------------------------------------------
update 表名 set tel=555 where id=1; #修改tb_door表中id为1的记录
#修改 设置 表里的字段名=修改后的新值
--------------------------------------------------------------------
delete from tb_order_detail;
#删除 表 表名
----------------------------------------------------------------
#主键约束 primary key
#字段的值必须唯一,且不能为空,使用primary key
当主键为数值类型时,为了方便维护,可以设置主键自增策略(auto_increment),
设置了主键自增策略后,数据库会在表中保存一个AUTO_INCREMENT变量值,初始值为1,
当需要id值,不需要我们指定值,由数据库负责从AUTO_INCREMENT获取一个id值,
作为主键值插入到表中。而且每次用完AUTO_INCREMENT值,都会自增1.
————————————————-------------------------------------
非空约束 not null
如果为一个列添加了非空约束,那么这个列的值就不能为空,但可以重复
--------------------------------------------------------------------
唯一约束 unique
哪个字段添加了唯一约束,从此,字段值不能相同,使用unique
--------------------------------------------------------------------
lower--全转小写
SELECT ename,LOWER(ename) FROM emp;参数是列名
--------------------------------------------------------
upper--全转大写
SELECT ename,UPPER(ename) a FROM emp;参数是列名
-------------------------------------------------------
length--数据的长度,根据utf8,一个字母或数字长度为1,一个汉字长度为3
SELECT ename,LENGTH(ename) FROM emp;#查询ename的长度
-----------------------------------------------------------------------
substr--截取子串
substr(列名,a,b)a是截取谁,b是从哪个字符开始
SELECT ename,SUBSTR(ename,2) FROM emp;#从第二个截取到结束
SELECT ename,SUBSTR(ename,2,2) FROM emp;#第二个开始,截取2个数
------------------------------------------------------------------------
concat--拼接数据
concat(a,b,...)拼串--a是列名,b是要拼接的数据,...可以有多个参数
SELECT ename,CONCAT(ename,'hello',1,2) FROM emp;
-------------------------------------------------------------------------
replace--替换
replace(a,b,c)替换--a是字段名,把b换成c
SELECT ename,REPLACE(ename,'a','666')FROM emp;
-------------------------------------------------------------------------
ifnull(a,b)--a是字段名,b是要换成的值
SELECT comm,IFNULL(comm,100) FROM emp;#如果是null就换成100
--------------------------------------------------------------------------
round(a,b):四舍五入--a是列名,b是保留几位小数
SELECT comm,ROUND(comm) FROM emp;#四射五入取整
SELECT comm,ROUND(comm,1) FROM emp;#四舍五入保留一位小数
ceil:向上取整
SELECT comm,CEIL(comm) FROM emp;
floor:向下取整
SELECT comm,FLOOR(comm) FROM emp;
--------------------------------------------------------------------------
#对日期数据的函数
#now & year & month & day
SELECT NOW();#当前时间
SELECT YEAR('2019-3-12')
SELECT YEAR(NOW());#当前年
SELECT MONTH(NOW()),DAY(NOW());#当前月,当前日
#hour时 minute分 second秒
SELECT HOUR(NOW()),MINUTE(NOW()),SECOND(NOW());#当前时分秒
SELECT YEAR(NOW()),MONTH(NOW()),DAY(NOW()),HOUR(NOW()),MINUTE(NOW()),SECOND(NOW());
---------------------------------------------------------------------------
#生成一个32位随机数
SELECT UUID();
#\表示转义符号,把'当做普通的字符在使用,而不是字符串的标记
SELECT 'xi\'an';
----------------------------------------------------------------------------
#条件查询
#1.去重disrinct
SELECT loc FROM dept;
SELECT DISTINCT loc FROM dept;#查询部门地址
#2.where 连接查询的条件
#select 字段名 from表名 where 字段名=字段值
#练习1:查询编号为1的部门信息
SELECT * FROM dept WHERE deptno=1;
#练习2:查询编号>1的部门信息
SELECT * FROM dept WHERE deptno>2;
SELECT * FROM dept WHERE deptno<2;
SELECT * FROM dept WHERE deptno!=1;
SELECT * FROM dept WHERE deptno<>1;#表示不等于,同上
#练习三:查询名称是research的部门编号
SELECT deptno FROM dept WHERE dname='research';
----------------------------------------------------------------------------
#查询部门地址在二区的部门名称
SELECT dname FROM dept WHERE loc='二区';
#查询部门地址在二区名字里有o的部门编号
SELECT deptno FROM dept WHERE loc='二区' AND dname LIKE '%o%';
#查询名字以1开头的员工岗位并去重
SELECT DISTINCT job FROM emp WHERE ename LIKE 'l%';
#查询15年到19年入职的员工姓名和岗位
SELECT job,ename FROM emp WHERE
YEAR(hiredate)>=2015 AND YEAR(hiredate)<=2019;
#查询副总的年薪
SELECT sal*12+IFNULL(comm,0)*12 FROM emp WHERE job='副总';
---------------------------------------------------------------------
#1.null的数据用is/is not关键字来过滤
#练习1:查询没有奖金的员工信息
SELECT * FROM emp WHERE comm IS NULL;
#查询有奖金的员工
SELECT * FROM emp WHERE comm IS NOT NULL;
-----------------------------------------------------------------------
#2 between and
#练习:查询工资在5000~10000的员工信息
SELECT * FROM emp WHERE sal>=5000 AND sal <=10000;
SELECT * FROM emp WHERE sal BETWEEN 5000 AND 10000;# [5000,10000];
#查19年入职的员工姓名
SELECT ename FROM emp WHERE hiredate BETWEEN '2019-1-1' AND '2019-12-31';
SELECT ename FROM emp WHERE YEAR(hiredate)=2019;#同上
SELECT ename FROM emp WHERE YEAR(hiredate) BETWEEN 2019 AND 2019;#同上
-------------------------------------------------------------------------
#3 limit 数字1,数字2--分页,数字1是从下标开始展示,,数字2表示展示行数
#练习:展示前两条员工信息
SELECT * FROM emp LIMIT 2; #只取前n条的数据
SELECT * FROM emp LIMIT 1,4; #从1+1的数据开始,总共展示4条
#练习:查询岗位是员工的第一条记录
SELECT * FROM emp WHERE (job='员工') LIMIT 0,1 ;#limit 通常放最后
---------------------------------------------------------------------------
#4 order by 排序,默认是升序ASC,+desc为降序
#练习:按照工资排序
SELECT * FROM emp ORDER BY sal;#升序排序
SELECT * FROM emp ORDER BY sal DESC;#按数值降序排序
#练习:按照名字排序
SELECT * FROM emp ORDER BY ename DESC;#按字母降序
#练习:按照岗位排序
SELECT * FROM emp ORDER BY job ASC;#按汉字对应的编号升序
#练习:查询15年到19年入职的员工信息只取前两条,并按照工资升序排序
SELECT * FROM emp WHERE
YEAR(hiredate) BETWEEN 2015 AND 2019 #区间[2015,2019]
ORDER BY sal ASC #排序,默认的升序
LIMIT 2;#分页,只取前两条,通常放最后
--------------------------------------------------------------------------
#统计需求
#练习:统计每个员工的年薪
SELECT *,sal*12+IFNULL(comm,0)*12 FROM emp ;
#统计19年以前入职的员工信息
SELECT * FROM emp WHERE YEAR(hiredate)<2019;
--------------------------------------------------------------------------
#聚合函数max min sum avg count
#练习1:求最高薪的员工信息
SELECT MAX(sal) FROM emp;
#求员工的最低薪,总和,平均数,记录总数
SELECT MIN(sal) FROM emp;#最小值
SELECT SUM(sal) FROM emp;#总和
SELECT AVG(sal) FROM emp;#平均数
#最大值 #最小值 #平和 #平均数
SELECT MAX(sal),MIN(sal),SUM(sal),AVG(sal) FROM emp;
#员工表里一共有几条记录
SELECT COUNT(*) FROM emp;#低效
SELECT COUNT(1) FROM emp;#高效
SELECT COUNT(sal) FROM emp;#了解,不推荐
SELECT COUNT(comm) FROM emp;#按照字段统计师不统计null
---------------------------------------------------------------------------
#练习:统计名字里包含a的总数记录
SELECT COUNT(1) FROM emp WHERE ename LIKE '%a%'
#练习:统计19年入职的员工里的最高薪
SELECT MAX(sal) FROM emp WHERE YEAR(hiredate)=2019;
#练习:统计2号部门的平均薪资
SELECT AVG(sal)FROM emp WHERE deptno=2;
#练习:统计2号部门一年的工资支出
SELECT SUM(sal*12+IFNULL(comm,0)*12) FROM emp WHERE deptno = 2;#工资加奖金支出
SELECT SUM(sal)*12 FROM emp WHERE deptno = 2;#工资支出
----------------------------------------------------------------------------
#分组:使用关键字 group by
#练习:统计每个部门的平均薪资
SELECT AVG(sal),deptno FROM emp GROUP BY deptno;#混合查聚合列和非聚合列必须要分组
#练习:统计每个部门的最高薪资
#查询结果中出现了混合列,包裹着聚合列和非聚合列
SELECT MAX(sal),deptno FROM emp GROUP BY deptno;#分组口诀:通常按照非聚合列分组
#练习:统计每年入职的总人数
SELECT COUNT(1),YEAR(hiredate) FROM emp GROUP BY YEAR(hiredate);
#练习统计每个岗位的平均薪资
SELECT AVG(sal),job FROM emp GROUP BY job ;
#having 把分组后的数据还想继续过滤,
#练习统计每个岗位的平均薪资,而且只要>=10000的
SELECT AVG(sal),job FROM emp GROUP BY job HAVING AVG(sal)>=10000;
SELECT AVG(sal) AVG,job FROM emp GROUP BY job HAVING AVG>=10000;#同上,分组后的过滤,avg是别名
#SELECT AVG(sal) AVG,job FROM emp where AVG>=10000;#where里不能用别名,也不能出现聚合函数
#练习:统计每年入职的人数,并且只要19年的
SELECT COUNT(1),YEAR(hiredate) a FROM emp
WHERE YEAR(hiredate)=2019
GROUP BY YEAR(hiredate)=2019 #分组
#having a=2019;#分组后过滤
SELECT COUNT(1),YEAR(hiredate) a FROM emp WHERE YEAR(hiredate)=2019
#where比 having高效,因为执行时机早
#having 把分组后的数据还想继续过滤,
#练习统计每个岗位的平均薪资,而且只要>=10000的
SELECT AVG(sal),job FROM emp GROUP BY job HAVING AVG(sal)>=10000;
SELECT AVG(sal) AVG,job FROM emp GROUP BY job HAVING AVG>=10000;#同上,分组后的过滤,avg是别名
#SELECT AVG(sal) AVG,job FROM emp where AVG>=10000;#where里不能用别名,也不能出现
SELECT * FROM emp ORDER BY sal DESC;
SELECT * FROM emp ORDER BY sal DESC,job ASC;
SELECT * FROM emp ORDER BY deptno DESC,job ASC;
SELECT COUNT(1) FROM emp WHERE ename LIKE '%a%';
#查询每个岗位的员工个人数
SELECT job,COUNT(*) FROM emp GROUP BY job;
#什么时候需要分组,查询时出现了混合列
#统计每个部门包含re的部门编号
SELECT deptno FROM dept WHERE dname LIKE 're%'
GROUP BY loc;
#统计每年入职的员工的最高薪资,只要>5000的
SELECT MAX(sal),YEAR(hiredate) FROM emp
GROUP BY YEAR(hiredate) #分组
#having里可以用聚合函数,where 不能
HAVING MAX(sal)>5000 #分组后过滤
#查询所有员工的最高薪-用分页
SELECT sal FROM emp ORDER BY sal DESC LIMIT 1
CREATE TABLE USER(
id INT(11) PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(20),pwd VARCHAR(10));
INSERT INTO USER VALUES(NULL,'jack',"123");
INSERT INTO USER VALUES(NULL,'rose',"456");
#对上面SQL中使用的事物进行优化,因为上面的SQL需要两个事物开启
#下面这种SQL也叫做批量插入的功能,高效,多次插入使用同一个事务
INSERT INTO USER VALUES(NULL,'tnoy',"123"),(NULL,'jerry',"456")
#默认约束:给字段设置默认值而不是null,使用default
CREATE TABLE a(
id INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
sex VARCHAR(10) DEFAULT '男')
#检查约束:使用check,
CREATE TABLE b(
id INT PRIMARY KEY AUTO_INCREMENT,
age INT,
CHECK(age<100 AND age>0 OR ?)#了解,数据要满足检查条件才可以
)
#外键约束:
CREATE TABLE tb_user(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(20),
age INT(3),
sex VARCHAR(10) DEFAULT '男'#默认约束
)
CREATE TABLE tb_user_address(
user_id INT PRIMARY KEY,
address VARCHAR(200),
#创建外键
#FOREIGN KEY(当前表主键名) REFERENCES 对方表(对方的主键)
FOREIGN KEY(user_id) REFERENCES tb_user(id)#创建外键
)
#使用外键
#约束的情况1:子表的主键值 必须 取自 主表的主键值
#约束的情况2:主表的记录,没有被子表使用,才可以删
#如果表存在就删除
DROP TABLE IF EXISTS courses;
DROP TABLE IF EXISTS scores;
DROP TABLE IF EXISTS students;
DROP TABLE IF EXISTS teachers;
#课程表
CREATE TABLE courses(
cno VARCHAR(5) NOT NULL,
cname VARCHAR(10) NOT NULL,
tno VARCHAR(3) NOT NULL,
PRIMARY KEY (cno)
);
#得分表
CREATE TABLE scores(
sno VARCHAR(3) NOT NULL,
cno VARCHAR(5) NOT NULL,
degree NUMERIC(10,1) NOT NULL,
PRIMARY KEY (sno, cno)
);
#学生表
CREATE TABLE students(
sno VARCHAR(3) NOT NULL,
sname VARCHAR(4) NOT NULL,
ssex VARCHAR(2) NOT NULL,
sbirthday DATETIME,
class VARCHAR(5),
PRIMARY KEY (sno)
);
#老师表
CREATE TABLE teachers(
tno VARCHAR(3) NOT NULL,
tname VARCHAR(4),
tsex VARCHAR(2),
tbirthday DATETIME,
prof VARCHAR(6),
depart VARCHAR(10),
PRIMARY KEY (tno)
);
INSERT INTO STUDENTS (SNO,SNAME,SSEX,SBIRTHDAY,CLASS) VALUES (108 ,'曾华' ,'男' ,'1977-09-01',95033);
INSERT INTO STUDENTS (SNO,SNAME,SSEX,SBIRTHDAY,CLASS) VALUES (105 ,'匡明' ,'男' ,'1975-10-02',95031);
INSERT INTO STUDENTS (SNO,SNAME,SSEX,SBIRTHDAY,CLASS) VALUES (107 ,'王丽' ,'女' ,'1976-01-23',95033);
INSERT INTO STUDENTS (SNO,SNAME,SSEX,SBIRTHDAY,CLASS) VALUES (101 ,'李军' ,'男' ,'1976-02-20',95033);
INSERT INTO STUDENTS (SNO,SNAME,SSEX,SBIRTHDAY,CLASS) VALUES (109 ,'王芳' ,'女' ,'1975-02-10',95031);
INSERT INTO STUDENTS (SNO,SNAME,SSEX,SBIRTHDAY,CLASS) VALUES (103 ,'陆君' ,'男' ,'1974-06-03',95031);
INSERT INTO TEACHERS(TNO,TNAME,TSEX,TBIRTHDAY,PROF,DEPART) VALUES (804,'易天','男','1958-12-02','副教授','计算机系');
INSERT INTO TEACHERS(TNO,TNAME,TSEX,TBIRTHDAY,PROF,DEPART) VALUES (856,'王旭','男','1969-03-12','讲师','电子工程系');
INSERT INTO TEACHERS(TNO,TNAME,TSEX,TBIRTHDAY,PROF,DEPART) VALUES (825,'李萍','女','1972-05-05','助教','计算机系');
INSERT INTO TEACHERS(TNO,TNAME,TSEX,TBIRTHDAY,PROF,DEPART) VALUES (831,'陈冰','女','1977-08-14','助教','电子工程系');
INSERT INTO COURSES(CNO,CNAME,TNO)VALUES ('3-105' ,'计算机导论',825);
INSERT INTO COURSES(CNO,CNAME,TNO)VALUES ('3-245' ,'操作系统' ,804);
INSERT INTO COURSES(CNO,CNAME,TNO)VALUES ('6-166' ,'模拟电路' ,856);
INSERT INTO COURSES(CNO,CNAME,TNO)VALUES ('6-106' ,'概率论' ,831);
INSERT INTO COURSES(CNO,CNAME,TNO)VALUES ('9-888' ,'高等数学' ,831);
INSERT INTO SCORES(SNO,CNO,DEGREE)VALUES (103,'3-245',86);
INSERT INTO SCORES(SNO,CNO,DEGREE)VALUES (105,'3-245',75);
INSERT INTO SCORES(SNO,CNO,DEGREE)VALUES (109,'3-245',68);
INSERT INTO SCORES(SNO,CNO,DEGREE)VALUES (103,'3-105',92);
INSERT INTO SCORES(SNO,CNO,DEGREE)VALUES (105,'3-105',88);
INSERT INTO SCORES(SNO,CNO,DEGREE)VALUES (109,'3-105',76);
INSERT INTO SCORES(SNO,CNO,DEGREE)VALUES (101,'3-105',64);
INSERT INTO SCORES(SNO,CNO,DEGREE)VALUES (107,'3-105',91);
INSERT INTO SCORES(SNO,CNO,DEGREE)VALUES (108,'3-105',78);
INSERT INTO SCORES(SNO,CNO,DEGREE)VALUES (101,'6-166',85);
INSERT INTO SCORES(SNO,CNO,DEGREE)VALUES (107,'6-106',79);
INSERT INTO SCORES(SNO,CNO,DEGREE)VALUES (108,'6-166',81);
#多表联查 三种方式
#方式一:笛卡尔积,用逗号隔开多张表
SELECT * FROM emp,dept;#产生了大量的结果集
#描述两张表的关系,表名.字段名
SELECT * FROM emp,dept WHERE dept.deptno=emp.deptno;#描述两张表的关系
#练习:查询部门表的部门名称,展示员工表所有数据
SELECT emp.*,dept.dname FROM dept,emp WHERE dept.deptno= emp.deptno
#练习:查询部门的所有成员和员工的名字,但是不要部门名称叫accounting的数据
SELECT dept.*,emp.ename FROM dept,emp#逗号隔开表名
WHERE dept.deptno=emp.deptno #表关系
AND dept.dname='accounting';#业务条件
#练习:查询所有数据,条件是部门编号>1的
SELECT dept.*,emp.* FROM dept,emp
WHERE dept.deptno=emp.deptno
AND emp.deptno>1
#练习:查询易天老师能讲的课程名称
SELECT courses.cname FROM teachers,courses
WHERE courses.tno=teachers.tno
AND teachers.tname='易天';
#练习:查询计算机导论课程的总分
SELECT SUM(degree) FROM courses,scores
WHERE courses.cno=scores.cno
AND courses.cname='计算机导论'
#方式二:连接查询,用join连接多张表 on后面是条件
SELECT * FROM dept JOIN emp;#用jpin连接多张表
SELECT * FROM dept JOIN emp
ON dept.deptno=emp.deptno#表关系
#练习:查询部门名称和员工表的所有数据
SELECT dept.dname,emp.* FROM dept JOIN emp
ON dept.deptno=emp.deptno#表关系
#练习:查询部门的所有成员和员工的名字,但是不要部门名称叫accounting的数据
SELECT dept.*,emp.ename FROM dept JOIN emp
ON dept.deptno=emp.deptno #表关系
WHERE dept.dname='accounting' #业务条件
#练习:查询所有部门和员工数据,条件是部门编号>1的
SELECT * FROM dept JOIN emp
ON dept.deptno=emp.deptno
WHERE dept.deptno>1
#练习:查询易天老师能讲的课程名称
SELECT courses.cname FROM courses JOIN teachers
ON courses.tno=teachers.tno
WHERE teachers.tname='易天'
#练习:查询计算机导论课程的总分
SELECT SUM(scores.degree) FROM courses JOIN scores
NO courses.cno=scores.cno
WHERE courses.cname='计算机导论'
#测试三种连接的区别
#有两种连接查询:内连接和外连接(左外连接,右外连接)
#innerjoin:查两张表的交集
#leftjoin:左边表的所有和左边满足条件的
#reght join:右边表的所有和左边满足条件的
#内连接:取交集,取左右表都满足条件的
SELECT * FROM dept INNER JOIN emp
ON dept.deptno=emp.deptno#取交集
#左外连接:取左表的所有和右表满足条件的不满足的都是null
SELECT * FROM dept LEFT JOIN emp
ON dept.deptno=emp.deptno
#右外连接:取右表的所有和左表满足条件的不满足的都是null
SELECT * FROM emp RIGHT JOIN dept
ON dept.deptno=emp.deptno
#连接查询的效率:小表驱动大表
#把结构简单或者数据量勺的表放在前面作为左表
#因为左表会查所有数据,右表只查满足了条件的那些数据