最近在学习数据库技术,并且把视频中的知识点进行了汇总,字数较多,仅供参考。
会持续更新
欢迎读者提出问题与错误,一起交流~
DB:数据库,保存一组有组织的数据的容器。
DBMS:数据库管理系统:又称为数据库软件(产品),用于管理DB中的数据。
SQL:结构化查询语言,用于和DBMS通信的语言。
将数据先放到表里面,再把表放到库里。
一个数据库中可以有多张表,每个表都有一个的名字,用来标识自己,表名具有唯一性。
表具有一些特性,这些特性定义了数据在表中如何存储,类似java中类的设计。
表由列组成,我们也称为字段,所有表都是由一个或者多个列组成的,每一个列类似于Java中的属性。
MySQL不区分大小写,但建议关键字大写,表名,列名小写。
每条命令最好用分号结尾。
每条命令根据需要,可以进行缩进和换行。
注释:单行注释: # 注释文字 单行注释: – 注释文字 多行注释: /* 645465 */
DQL语言的学习(数据查询语言)(针对于查询(select))
DML语言的学习(数据操作语言)(针对于增删改)
DDL语言的学习(数据定义语言)(针对库和表的定义,创建删除等)
TCL语言的学习(事物控制语言)
DQL学习
select 查询列表 from 表名;
类似于: System.out.println(‘’打印的东西‘’);
特点:查询列表可以是:表中的字段、常量值、表达式、函数。查询的结果是一个虚拟的表格。
SELECT last_name FROM employees;
SELECT last_name,salary,email FROM employees;
SELECT * FROM employees;
SELECT 100;
SELECT 'john';
SELECT 100*98;
SELECT 100%98;
SELECT VERSION();
1.便于理解。
2.如果要查询的字段有重名的情况,使用别名可以区分开来
方式一
SELECT 100%98 AS 结果;
SELECT last_name AS 姓,first_name AS 名 FROM employees;
方式二
SELECT last_name 姓, first_name 名 FROM employees;
案例:查询salary ,显示结果是 out put。
SELECT salary AS "OUT put" FROM employees;
里面只可以放一个
案例 :查询员工表中涉及到的所有部门编号
SELECT DISTINCT department_id FROM employees;
java中的+号作用:
1.运算符(数值型)
2.连接符,只要有一个操作数为字符串。
mysql中的+号只有一个功能:运算符
select 100+90;
两个操作数都是数值型,则做加法
select '123'+90;
(为90)
其中一方为字符型,试图将字符型数值转换为数值型
如果转换成功,就继续左加法运算。如果转换失败,则将字符型数值转换成0
select null+10;
为null
案例:查询员工名和姓链接成一个字段,并显示为姓名
SELECT
CONCAT(last_name,first_name) AS 姓名
FROM
employees;
着重号,用于区分NAME(关键字)和NAME(表内容)的区别。
建议还是不要使用 ,当需要命名name时,可以将name前面加上一些别的字母,用来于关键字区别。
如:s_name,t_name 等。
语法:
select
查询列表
from
表名
where
筛选条件;
分类:
条件运算符: > < =(等于) <>(不等) >= <=
案例一:查询工资大于12000的员工。
SELECT * FROM employees WHERE salary>12000 ;
案例二:查询部门编号不等于90号的员工名和部门编号。
SELECT
last_name , department_id
FROM
employees
WHERE
department_id<>90;
# 或者 department_id!=90
作用:用于连接条件表达式
逻辑运算符 : && || !
推荐:and or not
案例一:查询工资在10000-20000之间的员工名、工资以及奖金。
SELECT
last_name,salary,commission_pct
FROM
employees
WHERE
salary>=10000&&salary<=20000;
#或者用and
案例二:查询部门编号不是在90-110之间,或者工资大于15000的员工信息。
SELECT
*
FROM
employees
WHERE
department_id > 110 or department_id< 90 OR salary>15000;
或者:
SELECT
*
FROM
employees
WHERE
NOT(department_id>=90 AND department_id<=110) OR salary>15000;
like、between and、in、is null
特点:一般和通配符搭配使用
通配符:
% 任意多个字符(包含零个)
_ 任一单个字符
案例一:查询员工名中包含字符a的员工信息。
SELECT
*
FROM
employees
WHERE
last_name LIKE '%a%' ;
案例二:查询员工中第三个字符为e,第五个字符为a的员工名和工资。
SELECT
last_name,salary
FROM
employees
WHERE
last_name LIKE '___e_a%';
案例三:查询员工名中第二个字符为下划线的员工名。
SELECT
last_name
FROM
employees
WHERE
last_name LIKE '_\_%';
使用between and可以提高语句的简洁度,包含两个临界值,两个临界值不要颠倒顺序。
案例一:查询员工编号在100-120之间的员工信息。
SELECT
*
FROM
employees
WHERE
employee_id BETWEEN 100 AND 120;
含义:判断某字段的值是否属于in列表中的某一项。
特点:1.使用in提高语句简洁度。
2.in列表的值类型必须统一或者兼容。
案例一:查询员工的工种编号是IT_RPOG、AD_VP、AD_PRES中的一个员工名和工种编号
SELECT
last_name,job_id
FROM
employees
WHERE
job_id IN ('IT_RPOG','AD_VP','AD_PRES');
案例一:查询到没有奖金的员工和奖金率。
SELECT
last_name,commission_pct
FROM
employees
WHERE
commission_pct IS NOT NULL;
安全等于:相当于是否等于
案例一:
SELECT
last_name,commission_pct
FROM
employees
WHERE
commission_pct <=>NULL;
1.可以持久化数据到本地。
2.结构化查询。
1.DB:数据库。
2.DBMS:数据库管理系统,又称为数据库软件或者数据库产品,用于创建或者管理DB。
3.SQL:结构化查询语言,用于和数据库通信的语言,不是某个软件所特有的,是都用这个。
1.数据存放到表中,然后表再放到库中。
2.一个库中可以有多张表,每张表具有唯一的表名来标识自己。
3.表中有一个或者多个列,列又称为字段,相当于Java中的属性。
4.表中的每一个数据,相当于Java中的对象 。
MySQL oracle db2 sqlserver
语法:
SELECT
查询列表
FROM
表
【WHERE 筛选条件】
ORDER BY 排序列表 【asc|desc】
ASC从低到高(不填默认为升序) desc从高到低
ORDER BY 子句中可以支持单个字段、多个字段、表达式、函数、别名
ORDER BY 子句一般放在查询语句的最后面,除了limit子句。
注:【】表示可以有也可以无
案例一:查询员工信息。要求工资从高到低排序、从低到高。
SELECT
*
FROM
employees
ORDER BY
salary DESC;
SELECT
*
FROM
employees
ORDER BY
salary ;
案例二:查询部门编号>=90的员工信息,按入职时间的先后顺序进行排序。
SELECT
*
FROM
employees
WHERE
department_id>=90
ORDER BY
hiredate ASC;
案例三:【按表达式排序】 按年薪的高低显示员工的信息和年薪。
SELECT
* ,salary*12*(1+IFNULL(commission_pct,0)) #年薪
FROM
employees
ORDER BY
salary*12*(1+IFNULL(commission_pct,0)) DESC;
#利用别名更好
ORDER BY 年薪 DESC;
案例四:按姓名的长度显示员工的姓名和工资【按函数排序】。
SELECT
LENGTH(last_name) 字节长度,last_name,salary
FROM
employees
ORDER BY
LENGTH(last_name) DESC;
案例五:查询员工信息,要求先按工资升序,再按员工编号降序【按多个字段排序】。
SELECT
*
FROM
employees
ORDER BY
salary ASC,employee_id DESC;
功能:类似于Java的方法,将一组逻辑语句封装在方法中,对外暴露方法名。
好处:
1.隐藏了实现细节 。
2.提高代码的重用性 。
调用:
SELECT 函数名(实参列表) 【FROM 表】;
特点:1.函数名 2.函数功能
分类:
1.单行函数 如:CONCAT length IFNULL
2.分组函数:又称为统计函数,聚合函数,组函数 用于统计使用
length:获取子节个数
SELECT LENGTH('jack');
SELECT LENGTH('哈哈哈');# 一个汉字是三个子节
concat:拼接字符串
SELECT
CONCAT(last_name,'_',first_name)
FROM
employees;
upper、lower: 大小写转换
SELECT UPPER('ohhh');
SELECT LOWER('DADASDA');
实例:将姓变成大写,名变成小写
SELECT
CONCAT(UPPER(last_name),LOWER(first_name)) 姓名
FROM
employees;
SUBSTR、 SUBSTRING: 字符串裁剪
注意:索引是从1开始的
案例:截取从指定索引处后面的所有字符
SELECT SUBSTR('李莫愁爱上了路展元',7) out_put;#输出路展元
案例:截取从指定索引处指定字符长度的字符
SELECT SUBSTR('李莫愁爱上了路展元',1,3) out_put;#输出李莫愁
案例:姓名中首字符大写,其他字符小写然后用_拼接,显示出来
SELECT
CONCAT(UPPER(SUBSTR(last_name,1,1)),'_',LOWER(SUBSTR(last_name,2))) out_put
FROM
employees;
INSTR: 返回子串第一次出现的索引,如果找不到返回0
SELECT INSTR('杨不悔爱上了印巴下','印巴下') AS out_put;
trim :去掉前后的空格或者指定的字符
SELECT LENGTH(TRIM(' 张翠山 ')) AS out_put;
SELECT TRIM('a' FROM'aaaaaaaaa大aaa旭aaaaa') AS out_put;
lpad: 用指定的字符实现左填充指定长度
SELECT LPAD('畅',5,'#');
rpad: 右填充
SELECT RPAD('畅',5,'@');
replace :替换
SELECT REPLACE('Java畅学Java','Java','SQL');
round:四舍五入
SELECT ROUND(1.55);#1.6
SELECT ROUND(1.567,2);#1.57
ceil :向上取整
返回>=该参数的最小整数
SELECT CEIL(1.02);#2
floor: 向下取整
SELECT FLOOR(5.01);#5
truncate:截断
SELECT TRUNCATE(1.66,1);# 1.6
mod:取余
mod(a,b)相当于a-a/b×b
SELECT MOD(10,3);
now 返回当前系统日期+时间
SELECT NOW();
可以获取指定的部分,年月日小时分钟秒
SELECT YEAR(NOW()) 年;
SELECT YEAR('2001-05-03') 年;
curdate 返回日期不含时间
SELECT CURDATE();
curtime 返回时间不返回日期
SELECT CURTIME();
str_to_date 将字符通过指定格式转换成日期
SELECT STR_TO_DATE('1998-3-2','%Y-%c-%d')AS out_put;
if else效果
SELECT IF(10>4,'大','小');
SELECT last_name,commission_pct,IF(commission_pct IS NULL,'呜呜','哈哈') FROM employees;
1 :与switch case 一样的效果
case 要判断的字段或表达式
when 常量1 then 要显示的值或者语句1
when 常量1 then 要显示的值或者语句2
....
else 要显示的值或者语句n;
end
2:类似于多重if
case
when 条件一 then 要显示的值或者语句
when 条件二 then 要显示的值或者语句
...
else 要显示的值或者语句
end
案例: 显示不同编号的不同工资
SELECT salary 原始工资, department_id,
case department_id
when 30 then salary*1.1
when 40 THEN salary*1.2
WHEN 50 THEN salary*1.3
ELSE salary
END AS 新工资
FROM employees;
案例二 :查询员工工资情况, 如果大于20000显示a级别 大于15000显示b级别 大于10000显示c级别 否则显示d级别
SELECT salary 工资,
CASE
WHEN salary>20000 then 'a'
WHEN salary>15000 THEN 'b'
when salary>10000 THEN 'c'
ELSE 'd'
END
FROM employees;
分类:sum求和,avg平均,max,min,count(计算个数)
USE myemployees;
SELECT SUM(salary) 和 FROM employees;
SELECT AVG(salary) 平均 FROM employees;
SELECT MAX(salary) 最大 FROM employees;
SELECT MIN(salary) 最小 FROM employees;
SELECT COUNT(salary) 总计 FROM employees;
参数支持哪些类型
SELECT SUM(last_name), AVG(last_name) FROM employees;# sum和avg不支持字符/日期
忽略null
和distinct搭配
SELECT SUM(DISTINCT salary), SUM(salary) FROM employees;
SELECT COUNT(DISTINCT salary),COUNT(salary) FROM employees;
count 函数详细介绍
SELECT COUNT(*) FROM employees; # 显示行数
SELECT COUNT(1) FROM employees; # 显示行数 多加一列常量值,用来统计个数
效率
MYISAM 存储引擎下,count(*) 的效率最高
INNODB存储引擎下, count(*) 和 count(1)的效率差不多 ,比count(字段)效率高
语法:
SELECT
分组函数,列(要求出现在group by的 后面)
from
表
【WHERE 筛选条件】
GROUP BY
分组的列表
【order by 子句】
查询列表比较特殊:要求是分组函数和group by后出现的字段
特点:
1.分组查询中的筛选条件分为两类
数据源 | 位置 | 关键字 |
---|---|---|
分组前筛选 | 原始表 | group by 前面 WHERE |
分组后筛选 | 分组后的结果集 | group by后面 having |
分组函数做条件肯定放在having子句中
能用分组前筛选的,就优先使用
2.GROUP BY 子句支持单个字段分组,也支持多个字段分组(多个字段)
3.也可以添加排序(排序放在整个分组查询的最后)
案例:查询每个工种的最高工资
SELECT
MAX(salary),job_id
FROM
employees
GROUP BY
job_id;
案例:查询每个位置上的部门个数
SELECT
COUNT(*), location_id
FROM
departments
GROUP BY
location_id;
添加筛选条件
案例1:查询邮箱中包含字符a的,每个部门的平均工资
SELECT
AVG(salary),department_id
FROM
employees
WHERE
email like '%a%'
GROUP BY
department_id;
案例2:查询有奖金的每个领导手下员工的最高工资
SELECT
MAX(salary),manager_id
FROM
employees
WHERE
commission_pct is NOT NULL
GROUP BY
manager_id;
添加复杂的筛选条件
案例1:查询哪个部门的员工个数>2
#拆分为两步:
1.查询每个部们的员工个数
2.根据1的去筛选哪个部门的员工个数>2
SELECT
count(*),department_id
FROM
employees
GROUP BY
department_id
HAVING
count(*)>2;
案例2:查询每个工种有奖金的员工的最高工资>12000的工种编号和最高工资
SELECT
MAX(salary),job_id
FROM
employees
WHERE
commission_pct is NOT NULL
GROUP BY
job_id
HAVING
MAX(salary)>12000;
案例3:查询领导编号大于102的每个领导手下的最低工资>5000的领导编号是哪个
SELECT
MIN(salary),manager_id
FROM
employees
WHERE
manager_id>102
GROUP BY
manager_id
HAVING
MIN(salary)>5000;
按表达式(函数)分组
案例:按员工姓名的长度分组,查询每一组的员工个数,筛选员工个数>5的有哪写
1.查询每个长度的员工个数
SELECT
COUNT(*),LENGTH(last_name) len_name
FROM
employees
GROUP BY
LENGTH(last_name);
2.添加筛选条件
SELECT
COUNT(*),LENGTH(last_name) len_name
FROM
employees
GROUP BY
LENGTH(last_name)
HAVING
COUNT(*)>5;
按多个字段分组
案例:查询每个部门每个工种的员工的平均工资
SELECT
AVG(salary),department_id,job_id
FROM
employees
GROUP BY
department_id,job_id;
添加排序
案例:查询每个部门每个工种的员工的平均工资 ,并且按平均工资的高低显示
SELECT
AVG(salary),department_id,job_id
FROM
employees
GROUP BY
department_id,job_id
ORDER BY
AVG(salary) DESC;
又称为多表查询,当查询的字段来自于多个表时,就会用到连接查询。
笛卡尔乘积现象:表1 有m行 表2有n行 ,结果有m*n行
发生原因:没有有效的连接条件
如何避免:添加有效的连接条件
分类:
按年代分类:
sq192标准:仅仅支持内连接
sq199标准:【推荐】 就不支持全外连接
按功能分类:
内连接:等值连接、非等值连接、自连接
外连接:左外连接、右外连接、全外连接、交叉连接
1.等值连接的结果为多表的交集部分。
2.n表连接至少需要n-1个连接条件。
案例一:查询女神名和对应的男神名
SELECT
NAME,boyName
FROM
boys,beauty
WHERE
beauty.boyfriend_id =boys.id;
案例二:查询员工名和对应的部门名
SELECT
last_name, department_name
FROM
employees,departments
WHERE
employees.department_id=departments.department_id;
为表起别名
提高语句的简洁度,区别多个重名字段 (如果为表起了别名,查询时就不可以再用以前的表名了)
查询员工名,工种号,工种名
SELECT
last_name,e.job_id,job_title
FROM
employees e ,jobs j
WHERE
e.job_id =j.job_id;
可以加筛选
案例:查询有奖金的员工名和部门名
SELECT
last_name,department_name,e.commission_pct
FROM
employees e,departments d
WHERE
e.department_id=d.department_id
AND
e.commission_pct is NOT NULL;
案例2:查询城市名中第二个字符为‘o’的部门名和城市名
SELECT
department_name,city
FROM
departments d,locations l
WHERE
d.location_id=l.location_id
AND
city LIKE '_o%';
可以加分组
案例1.查询每个城市的部门个数
SELECT
COUNT(*) 个数,city
FROM
departments d,locations l
WHERE
d.location_id=l.location_id
GROUP BY
city;
案例2.查询有奖金的每个部门的部门名和部门的领导编号和该部门最低工资
SELECT
MIN(salary),d.manager_id,d.department_name
FROM
departments d ,employees e
WHERE
d.department_id=e.department_id
AND
e.commission_pct is NOT NULL
GROUP BY
department_name,d.manager_id;
可以加排序
案例:查询每个工种的工种名和员工的个数,并且按员工个数降序
SELECT
job_title,COUNT(*)
FROM
jobs j,employees e
WHERE
j.job_id=e.job_id
GROUP BY
job_title
ORDER BY
COUNT(*) DESC;
三表连接
案例:查询员工名、部门名、和所在城市名
SELECT
last_name,department_name,city
FROM
employees e,departments d,locations l
WHERE
e.department_id=d.department_id
AND
d.location_id=l.location_id
ORDER BY
department_name DESC;
案例1:查询员工的工资和工资级别
SELECT
salary,grade_level
FROM
employees e,job_grades j
WHERE
salary BETWEEN j.lowest_sal AND j.highest_sal;
案例:查询 员工名和上级的名称
SELECT
e.employees_id,e.last_name,m.employees_id,m.last_name
FROM
employees e,employees m
WHERE
e.manager_id = m.employee_id;
内连接:INNER
外连接:
1.左外:left
2.右外:right
3.全外:full
交叉连接:cross
语法:
SELECT
查询列表
from
表1 别名【连接类型】
join 表2 别名
on 连接条件
【where筛选条件】
【group by分组】
【having 筛选 条件】
【order by 排序列表】
语法:
SELECT
查询列表
from
表1 别名
inner join
表二 别名
on
连接条件;
分类:等值、非等值、自连接
特点:
1.inner可以省略
2.添加排序、分组和筛选
3.筛选条件放在where后面,连接条件放在了on后面、提高了分离性,便于阅读。
等值连接
查询员工名、部门名
SELECT
last_name,department_name
FROM
employees e
INNER JOIN
departments d
ON
e.department_id =d.department_id;
案例2:查询名字中包含e的员工名和工种名(添加筛选)
SELECT
last_name,job_title
FROM
employees e
INNER JOIN
jobs j
ON
e.job_id=j.job_id
WHERE
e.last_name like '%e%';
案例3:查询部门个数 >3的城市名和部门个数,(添加分组和筛选)
SELECT
city,COUNT(*)
FROM
departments d
INNER JOIN
locations l
on
d.location_id= l.location_id
GROUP BY
city
HAVING
COUNT(*)> 3;
案例4:查询哪个部门的员工个数>3的部门名和员工个数,并按个数降序(添加排序)
1:查询每个部门的员工个数
SELECT
COUNT(*) ,department_name
FROM
employees e
INNER JOIN
departments d
ON
e.department_id=d.department_id
GROUP BY
department_name;
2:在1的基础上筛选个数大于三的并记录
SELECT
COUNT(*) ,department_name
FROM
employees e
INNER JOIN
departments d
ON
e.department_id=d.department_id
GROUP BY
department_name
HAVING
COUNT(*)>3
ORDER BY
COUNT(*) DESC;
案例五:查询员工名,部门名,工种名,并按部门名称降序()
SELECT
last_name,department_name,job_title
FROM
employees e
INNER JOIN
departments d on e.department_id=d.department_id
INNER JOIN
jobs j ON j.job_id=e.job_id
ORDER BY
department_name DESC;
非等值连接
查询员工的工资级别
SELECT
salary,grade_level
FROM
employees e
JOIN
job_grades g
ON
e.salary BETWEEN g.lowest_sal AND g.highest_sal;
查询公司级别个数大于20,并按工资级别降序
SELECT
COUNT(*) ,grade_level
FROM
employees e
JOIN
job_grades g
on
e.salary BETWEEN g.lowest_sal AND g.highest_sal
GROUP BY
grade_level
HAVING
COUNT(*)>20
ORDER BY
grade_level DESC
自连接
查询员工的名字,上级的名字
SELECT
e.last_name,m.last_name
FROM
employees e
JOIN
employees m
ON
e.manager_id=m.employee_id;
查询姓名中包含k的员工的名字,上级的名字
SELECT
e.last_name,m.last_name
FROM
employees e
JOIN
employees m
ON
e.manager_id=m.employee_id
WHERE
e.last_name LIKE '%k%';
应用场景:查询一个表中有,另一个表中没有的记录
特点:1.外连接的查询结果为主表中的所有记录,如果从表中有和它匹配的,则显示匹配的值。如果没有匹配的,则显示null。
外连接的查询结果=内连接结果+主表中有而从表中没有的记录
2.左外连接,left join左边的是主表。
右外连接,left join右边是主表。
3.左外和右外如果交换两表顺序,可以实现同样的效果
4.全外连接=内连接中结果+表1中没有表2中有的+表1中有表2中没有
案例引入:查询男朋友,不在男神表中的女神名
左外连接
SELECT
b.name,bo.*
FROM
beauty b
LEFT OUTER JOIN
boys bo
ON
b.boyfriend_id=bo.id
WHERE
bo.id is NULL;
右外连接
SELECT
b.name,bo.*
FROM
boys bo
RIGHT OUTER JOIN
beauty b
ON
b.boyfriend_id=bo.id
WHERE
bo.id is NULL;
案例1:哪个部门没有员工
左外
SELECT
d.* ,e.employee_id
FROM
departments d
LEFT OUTER JOIN
employees e
ON
d.department_id=e.department_id
WHERE
e.employee_id IS NULL;
右外
SELECT
d.*,e.employee_id
FROM
employees e
RIGHT OUTER JOIN
departments d
ON
d.department_id=e.department_id
WHERE
e.employee_id IS NULL;
全外
USE girls;
SELECT
b.* , bo.*
FROM
beauty b
FULL OUTER JOIN
boys bo
on
b.boyfriend_id-bo.id;
交叉连接
SELECT
b.*,bo.*
FROM
beauty b
CROSS JOIN
boys bo;
含义:出现在其他语句中的select语句,称为子查询或者内查询
外部的查询语句,称为主查询或者外查询
分类:
按子查询出现的位置:
SELECT后面:仅仅支持标量子查询
from后面:支持表子查询
where或having后面:标量子查询、列子查询、行子查询
exits后面(相关子查询):表子查询
按结果集的行列数不同:
标量子查询(结果集只有一行一列)
列子查询(结果集只有一列多行)
行子查询(结果集只有一行多列)
表子查询(结果集为多行多列)
1.标量子查询(单行子查询)
2.列子查询(多行子查询)
3.行子查询(多列多行)
特点:
1.子查询放在小括号内,
2.子查询一般放在条件的右侧
3.标量子查询,一般搭配着单行操作符使用
> < >= <= <> =
4.列子查询一般搭配着多行操作符使用
in any/some all
案例一:谁的工资比 Abel高?
查询Abel的工资
SELECT
salary
FROM
employees
WHERE
last_name ='Abel';
查询员工的信息,满足条件1的结果
SELECT *
FROM
employees
WHERE salary > (
SELECT salary
FROM employees
WHERE last_name = 'Abel'
);
案例2:返回job_id与141号员工相同,salary比143号员工多 姓名,job_id和工资
查询141号的job_id
SELECT
job_id
FROM
employees
WHERE
employee_id = 141;
143号员工的salary
SELECT
salary
FROM
employees
WHERE
employee_id =143;
查询员工的姓名 job_id=1和工资>2
SELECT
last_name,job_id,salary
FROM
employees
WHERE job_id = (
SELECT job_id
FROM employees
WHERE employee_id = 141
) AND
salary >(
SELECT salary
FROM employees
WHERE employee_id =143
);
案例3:返回公司工资最少的员工last_name ,job_id和salary
查询工资最少
SELECT MIN(salary) FROM employees;
查询对应值 salary = 1.
SELECT
last_name,job_id,salary
FROM
employees
WHERE salary = (
SELECT MIN(salary)
FROM employees
);
案例4:查询最低工资 大于50号部门最低工资的部门id和其最低工资
查询50号部门的最低工资
SELECT
MIN(salary)
FROM
employees
WHERE
department_id = 50
查询每个部门的最低工资
SELECT
MIN(salary),department_id
FROM
employees
GROUP BY
department_id;
筛选2满足 min(salary)>1的结果
SELECT
MIN(salary),department_id
FROM
employees
GROUP BY
department_id
HAVING MIN(salary)> (
SELECT MIN(salary)
FROM employees
WHERE department_id = 50
);
案例1:返回location_id是1400或者是1700的部门中的所有员工姓名
查询location_id是1400或者1700的部门编号
SELECT
department_id
FROM
departments
WHERE
location_id in(1400,1700);
查询员工姓名,要求部门号是1列表中的某一个
SELECT
last_name
FROM
employees
WHERE department_id IN(
SELECT department_id
FROM departments
WHERE location_id in(1400,1700)
);
案例2:返回其他工种中比job_id 为‘IT_PROG’部门任一工资低的员工的员工号,姓名,job_id以及salary
查询job_id为‘IT_PROG’部门任一工资
SELECT DISTINCT
salary
FROM
employees
WHERE
job_id = 'IT_PROG';
查询员工号,姓名,job_id以及salary,salary 另一种写法 案例:查询员工编号最小并且工资最高的员工编号 查询最小的员工编号 查询出最高的工资 查询员工信息 另一种写法 放在select后面 案例:查询每个部门的员工个数 放在from后面 案例:查询每个部门的平均工资的工资等级 查询每个部门的平均工资 连接1的结果集和job_grades表,筛选条件平均工资 BETWEEN lowest_sal and highest_sal 应用场景:当要显示的数据,一页显示不全,需要分页提交sql请求 语法: 特点: 1.limit语句放在查询语句的最后,并且执行也是最后执行。 2.公式:要显示的页数是page,每页显示的条目数是size 案例1:查询前五条员工信息 或者 案例2:查询第11-25条的信息 案例3:有奖金的员工信息,并且工资较高的排名前10的员工信息 UNION 联合/合并 :将多条语句的查询结果合并成一个结果。 语法: 应用场景:要查询的结果来自于多个表,且多个表之间没有直接连接关系,但查询的信息一致时。 特点: 1.要求多条查询语句的查询列数是一致的 2.要求多条查询语句的查询的每一列的类型和顺序最好一致! 3.不想去重用 :UNION ALL,默认是去重的 引入的案例:查询部门编号>90或者邮箱包含a的员工信息 以前的方法 union方法 数据操纵语言: 数据插入:INSERT 数据修改:UPDATE 数据删除:DELETE 经典插入 语法: 1.插入的值类型要和列的类型兼容或一致 2.不可以为null的列必须插入值,可以为null的列是如何插入值的? 方式一:直接写NULL 方式二:列不写,NULL也不写 3.**列的顺序是否可以颠倒?**yes,可以。 4.列数和值的个数必须一致 5.可以省略列名,默认是所有列,而且列的顺序和表中列的顺序一致 直接插入案例 两种方式大PK 方式一有方式二无:支持插入多行(一次性加入多个数据行),支持子查询。 1.修改单表的记录 ★ 语法: 2.修改多表的记录【补充】 语法: sql92语法: Sql99语法: 案例1:修改单表的记录 修改beauty表中姓唐的女神的电话为156456465 案例2:修改boys表中的id号为2的名称为张非,并且魅力值改为10 2.修改多表的记录【补充】 案例1:修改张无忌的女朋友的手机号为“156465465” 案例2:修改没有男朋友的女神的男朋友编号都为2号(张飞) 方式一:delete 语法: (一删就是整行,所以需要加筛选条件) 1.单表删除 delete FROM 表名 where 筛选条件 2.多表删除【补充】 方式二:TRUNCATE 语法: TRUNCATE table 表名; (全部删掉) sql92语法: sql99语法: 方式一:delete 单表删除 案例一:删除手机号以9为结尾的女生信息 多表删除 案例:删除张无忌的女朋友的信息 案例:删除黄晓明的信息以及他女朋友的信息 DELETE pk TRUNCATE** 1.delete可以加where条件,TRUNCATE不可以。 2.TRUNCATE删除效率稍微高点。 3.假如要删除的表中有自增长列, 如果用delete删除后,再插入数据,自增长列的值从断点开始, 而truncate删除后。再插入数据,自增长列的值从1开始。 4.TRUNCATE 删除没有返回值,delete有。 5.TRUNCATE删除后不可以回滚,DELETE可以。 数据定义语言 库和表的管理 一、库的管理:创建、修改、删除 二、表的管理:创建、修改、删除 创建:create 修改:alter 删除:Drop 案例:创建表book 创建作者表author 修改列名、修改列的类型或者约束 添加新列、删除列、修改表名 修改列名 修改列的类型 添加新列 删除列 修改表名 通用的写法: 1.仅仅复制表的结构 2.复制表的结构+数据 3.只复制一部分 复制一部分,没内容 数值型: 整型 小数:定点数,浮点数 字符型: 较短的文本:char,varchar 较长的文本:text,blob(较长的二进制数字) 日期型 分类:TINYINT 1, SMALLINT 2, MEDIUMINT 3, int/INTEGER 4, BIGINT 8 (个子节) 特点: 1.如果不设置有无符号,默认是有符号,想设置无符号需要设置UNSIGNED 2.如果插入的数值超过了整型的范围,会报异常,并且插入的是临界值 3.如果不设置长度,会有默认的长度。 4.长度代表了显示的最大宽度,如果不够会用0在左边填充,但是必须搭配zerofill使用 如何设置无符号和有符号 浮点型:float(M,D) double(M,D) 定点型:dec(M,D) DECIMAL(M,D) 特点:1.关于M和D的意思—M:整数部位+小数部位 D:小数部位 如果超过范围,则插入临界值。 2.M和D都可以省略,如果是decimal,则M默认是10,D默认是0, 如果插入的是float或double,则会随着插入的数值的精度来决定精度。 对比:定点型的精度较高,如果要求插入的数值的精度较高,则优先使用它(货币运算等)。 举例子 较短的文本: char VARCHAR 其他: VARBINARY和binary适用于保存较短的二进制 enum用于保存枚举,set用于保存集合 较长的文本: text blob(较大的二进制) 比较: 分类: date只保存日期 time只保存时间 year只保存年 datetime保存日期+时间 TIMESTAMP保存日期+时间 比较: 一种限制,用于限制表中的数据,为了保证表中的数据的准确和可靠性 分类: NOT NULL :非空,用于保证该字段的值不能为空 比如姓名、学号等 DEFAULT:默认,用于保证该字段的值有默认值 比如性别 PRIMARY KEY :主键,用于保证该字段的值有唯一值,并且非空 比如学号、员工编号等 UNIQUE : 唯一,用于保证该字段的值有唯一值,可以为空 比如座位号 CHECK:检查约束【MySQL中不支持】[兼容性…不报错,但是没效果] 比如:年龄和性别 FOREIGN KEY :外键,用于限制两个表的关系,用于保证该字段的值必须来自于主表的关联列的值 比如:学生表的专业编号,员工表的部门编号,员工表的工种编号 1.创建表时 2.修改表时 1.列级约束 六大约束语法上都支持,但外键约束没有效果。 2.表级约束 除了非空,默认,其他的都支持。 创建表时添加约束 #1.添加列级约束 语法: 直接在字段名和类型后面追加约束类型即可 添加表级约束 在各个字段最下面 #通用写法: 主键和唯一的区别 1.均可以保证唯一性 2.主键不允许为空,唯一可以为空 3.主键最多为一个(0/1) 唯一可以有多个 4.都允许组合,但是不推荐 外键的特点 1.要求在从表设置外键关系 2.从表的外键列的类型和主表中的关联列的类型要求一致或者兼容,名称无要求 3.主表的关联列必须是个key(一般是主键或者唯一) 4.插入数据时,必须先插入主表(科目),再插入从表(学生), 删除数据时,先删除从表,再删除主表。 又称为自增序列 含义:可以不用手动的插入值,系统提供默认的序列值 特点:1.标识列和key搭配 2.一个表中可以有至多一个标识列 3.标识列类型只能是数值型 4.标识列可以通过 SET auto_increment_increment=3;设置步长,可以通过手动插入值,设置起始值。 创建表时设置标识列 修改表时设置标识列 修改表时删除标识列 事务:一个或一组sql语句组成一个执行单元,这个执行单元要么全部执行,要么全部不执行。 案例:转账 张三丰 1000 郭襄 1000 张三丰转给郭襄500 张三丰 500 郭襄 1500 1.原子性:原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生要么都不发生。 2.一致性:事务必须使数据库从一个一致性状态变成另外一个一致性状态。 3.隔离性:事务的隔离性是指一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务 是隔离的,并发执行的各个事务之间是不能互相干扰的。 4.持久性:持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的, 接下来的其他操作和数据库故障不应该对其有任何影响。 隐式事务:事务没有明显的开启和结束标记 比如:INSERT UPDATE DELETE 语句 显式事务:事务具有明显的开启和结束的标记(前提,必须先设置自动提交功能为禁用) 1.开启事务 SET autocommit=0;(关闭自动提交) 2.编写事务中的sql语句(SELECT INSERT UPDATE SELECT) 语句1; 语句2; … 3.结束事务 COMMIT; 提交事务 ROLLBACK; 回滚事务 NOT NULL :非空,用于保证该字段的值不能为空 比如姓名、学号等 DEFAULT:默认,用于保证该字段的值有默认值 比如性别 PRIMARY KEY :主键,用于保证该字段的值有唯一值,并且非空 比如学号、员工编号等 UNIQUE : 唯一,用于保证该字段的值有唯一值,可以为空 比如座位号 CHECK:检查约束【MySQL中不支持】[兼容性…不报错,但是没效果] 比如:年龄和性别 FOREIGN KEY :外键,用于限制两个表的关系,用于保证该字段的值必须来自于主表的关联列的值 比如:学生表的专业编号,员工表的部门编号,员工表的工种编号 1.创建表时 2.修改表时 1.列级约束 六大约束语法上都支持,但外键约束没有效果。 2.表级约束 除了非空,默认,其他的都支持。 创建表时添加约束 #1.添加列级约束 语法: 直接在字段名和类型后面追加约束类型即可 添加表级约束 在各个字段最下面 #通用写法: 主键和唯一的区别 1.均可以保证唯一性 2.主键不允许为空,唯一可以为空 3.主键最多为一个(0/1) 唯一可以有多个 4.都允许组合,但是不推荐 外键的特点 1.要求在从表设置外键关系 2.从表的外键列的类型和主表中的关联列的类型要求一致或者兼容,名称无要求 3.主表的关联列必须是个key(一般是主键或者唯一) 4.插入数据时,必须先插入主表(科目),再插入从表(学生), 删除数据时,先删除从表,再删除主表。 又称为自增序列 含义:可以不用手动的插入值,系统提供默认的序列值 特点:1.标识列和key搭配 2.一个表中可以有至多一个标识列 3.标识列类型只能是数值型 4.标识列可以通过 SET auto_increment_increment=3;设置步长,可以通过手动插入值,设置起始值。 创建表时设置标识列 修改表时设置标识列 修改表时删除标识列 事务:一个或一组sql语句组成一个执行单元,这个执行单元要么全部执行,要么全部不执行。 案例:转账 张三丰 1000 郭襄 1000 张三丰转给郭襄500 张三丰 500 郭襄 1500 1.原子性:原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生要么都不发生。 2.一致性:事务必须使数据库从一个一致性状态变成另外一个一致性状态。 3.隔离性:事务的隔离性是指一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务 是隔离的,并发执行的各个事务之间是不能互相干扰的。 4.持久性:持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的, 接下来的其他操作和数据库故障不应该对其有任何影响。 隐式事务:事务没有明显的开启和结束标记 比如:INSERT UPDATE DELETE 语句 显式事务:事务具有明显的开启和结束的标记(前提,必须先设置自动提交功能为禁用) 1.开启事务 SET autocommit=0;(关闭自动提交) 2.编写事务中的sql语句(SELECT INSERT UPDATE SELECT) 语句1; 语句2; … 3.结束事务 COMMIT; 提交事务 ROLLBACK; 回滚事务 SAVEPOINT 节点名;设置节点(保存点)类似于断点 演示delete:支持回滚: 演示truncate:不支持回滚 演示savepoint的使用 MySQL从5.0.1版本开始提供视图功能。一种虚拟存在的表,行和列的数据来自定义视图的查询中使用的表,并且 是在使用视图时动态生成的,只保存了sql逻辑,并不保存查询结果。 应用场景: 1.多个地方用到同样的查询结果 2.该查询结果使用sql语句较复杂 案例:查询姓张的学生名和专业名 普通解法 利用视图 案例1:查询邮箱中包含a字符的员工名、部门名和工种信息 案例2:查询各部门的平均工资级别 案例3:查询平均工资最低的部门信息 案例4:查询平均工资最低的部门名和工资 例: 系统变量: 全局变量 会话变量 自定义变量: 用户变量 局部变量 说明:变量由系统提供,不是用户定义,属于服务器层面。 使用的语法: 1.查看所有的系统变量 2.查看满足条件的部分系统变量 3.查看指定的某个系统变量的值 4.为某个系统变量赋值 方式一 方式二 注意:如果是全局级别,用GLOBAL 如果是会话级别,则需要加session,如果不写,则默认是session 作用域:服务器每次启动将为所有的全局变量赋初始值,针对于所有的会话(连接)有效,但不能跨重启。 1.查看所有的全局变量 2.查看部分的全局变量 3.查看指定的全局变量的值 4.为某个指定的全局变量赋值 作用域:仅仅针对于当前会话(连接)有效。 1.查看所有的会话变量 2.查看部分的会话变量 3.查看指定的会话变量的值 4.为某个指定的会话变量赋值 说明:变量是用户自定义的,不是由系统的。 使用步骤:声明、赋值、使用(查看、比较、运算等) 作用域:针对于当前会话(连接)有效,和会话变量的作用域一致应用在任何地方,也就是begin end里面或者begin end外面 赋值的操作符 : =或:= 1.声明并初始化 2.赋值(更新用户变量的值) 方式一:通过set或者select 例: 方式二:通过select INTO 例: 3.(使用)查看用户变量的值 作用域 :仅仅在定义他的begin END中有效,应用在begin end中的第一句话。 1.声明 2.赋值 方式一:通过set 或select 方式二:通过select INTO 3.使用 对比用户变量和局部变量 案例:声明两个变量并赋初始值,求和并打印 1.用户变量 2.局部变量 类似于Java中的方法,好处 1.提高代码的重用性 2.简化操作 含义:一组预先编译好的SQL语句的集合,理解成批处理语句 1.提高代码的重用性 2.简化操作 3.减少了编译次数并且减少了和数据库服务的连接次数,提高了效率。 注意: 1.参数列表包含三个部分: 参数模式 参数名 参数类型 举例: IN stuname VARCHAR(20); 参数模式: in :该参数可以作为输入:也就是该参数需要调用方传入值 OUT:该参数可以作为输出,也就是该参数可以作为返回值 inout:该参数既可以作为输入也可以作为输出,也就是该参数既需要传入值又可以返回值。 2.如果存储过程体仅仅只有一句话,begin END 可以省略 存储过程体中的每条SQL语句的结尾要求必须加分号。 存储过程的结尾可以使用 delimiter重新设置 语法:delimiter 结束标记 1.空参的存储过程 2.创建带in模式参数的存储过程 案例1:创建存储过程实现 根据女神名查询对应的男神信息 案例2:创建存储过程实现,用户是否登录成功 3.带out模式的存储过程 案例1:根据女神名,返回对应的男神名 案例2:根据女神名,返回对应的男神名和男神魅力值 4.带inout模式的存储过程 案例1:传入a和b两个值,最终要求a和b都翻倍并返回 题目1:创建存储过程实现传入用户名和密码,插入到admin表中 题目2:创建存储过程实现传入女神编号,返回女神名称和电话 题目3:创建存储过程或函数实现传入两个女神生日,返回大小 语法:drop procedure 存储过程名 含义:一组预先编译好的SQL语言的集合,理解成批处理语句 优点: 1.提高了代码的重用性 2.简化操作 3.减少了编译次数并且减少了和数据库服务器的连接次数,提高了效率 区别: 存储过程:可以有零个返回,也可以有多个返回。 函数:必须有且仅有一个返回,零个多个均不行。 1.参数列表包含两部分:参数名 参数类型 2.函数体:肯定会有return语句,如果没有会报错。如果return语句没有放在函数体的最后也不会报错,但是不建议。 3.函数体中仅有一句话,则可以省略begin end 4.使用delimiter语句设置结束标记 案例演示: 1.无参有返回 案例:返回公司的员工个数 2.有参有返回值 案例1:根据员工名,返回他的工资 案例2:根据部门名,返回该部门的平均工资。 案例:创建函数,实现传入两个float,返回二者之和 IF函数 功能:实现简单的双分支 语法: 应用:任何地方 case结构 情况1:类似于Java中的switch语句,一般用于实现的等值判断 语法: 情况2:类似于Java中的多重if语句,一般用于实现区间判断 特点: 1.可以作为表达式,嵌套在其他语句中使用,可以放在任何地方, BEGIN END 中或begin END 的外面 可以作为独立的语句去使用,只能放在begin end中 2.如果when中的值满足或条件成立,则执行对应的then语句并且结束case,都不满足则执行else中的语句或值 3.else可以省略,如果else省略,并且所有的when条件都不满足,则返回null if结构 功能:实现多重分支 语法: 应用在begin end中 分类:while loop repeat 循环控制: ITERATE 类似于continue ,继续 leave类似于break while 语法: LOOP 语法: REPEAT 语法: 案例: 批量插入,根据次数插入到admin表中多条记录(没有添加循环控制语句) 添加leave语句 案例:批量插入,根据次数插入到admin表中多条记录,如果次数>20则停止 笔记到这里就结束了,希望您能通过本文的阅读,掌握数据库的基础知识。 含义:一组预先编译好的SQL语言的集合,理解成批处理语句 优点: 1.提高了代码的重用性 2.简化操作 3.减少了编译次数并且减少了和数据库服务器的连接次数,提高了效率 区别: 存储过程:可以有零个返回,也可以有多个返回。 函数:必须有且仅有一个返回,零个多个均不行。 1.参数列表包含两部分:参数名 参数类型 2.函数体:肯定会有return语句,如果没有会报错。如果return语句没有放在函数体的最后也不会报错,但是不建议。 3.函数体中仅有一句话,则可以省略begin end 4.使用delimiter语句设置结束标记 案例演示: 1.无参有返回 案例:返回公司的员工个数 2.有参有返回值 案例1:根据员工名,返回他的工资 案例2:根据部门名,返回该部门的平均工资。 案例:创建函数,实现传入两个float,返回二者之和 IF函数 功能:实现简单的双分支 语法: 应用:任何地方 case结构 情况1:类似于Java中的switch语句,一般用于实现的等值判断 语法: 情况2:类似于Java中的多重if语句,一般用于实现区间判断 特点: 1.可以作为表达式,嵌套在其他语句中使用,可以放在任何地方, BEGIN END 中或begin END 的外面 可以作为独立的语句去使用,只能放在begin end中 2.如果when中的值满足或条件成立,则执行对应的then语句并且结束case,都不满足则执行else中的语句或值 3.else可以省略,如果else省略,并且所有的when条件都不满足,则返回null if结构 功能:实现多重分支 语法: 应用在begin end中 分类:while loop repeat 循环控制: ITERATE 类似于continue ,继续 leave类似于break while 语法: LOOP 语法: REPEAT 语法: 案例: 批量插入,根据次数插入到admin表中多条记录(没有添加循环控制语句) 添加leave语句 案例:批量插入,根据次数插入到admin表中多条记录,如果次数>20则停止 笔记到这里就结束了,希望您能通过本文的阅读,掌握数据库的基础知识。 笔者后面有时间也会将MySQL高级进阶笔记发出来,仅供大家学习。如果您觉得本文还不错,三连+关注一下我吧,我也会持续更新出高质量的文章。SELECT
last_name,employee_id,job_id,salary
FROM
employees
WHERE salary < any(
SELECT DISTINCT salary
FROM employees
WHERE job_id = 'IT_PROG'
)AND job_id <>'IT_PROG';
SELECT
last_name,employee_id,job_id,salary
FROM
employees
WHERE salary < (
SELECT MAX(salary)
FROM employees
WHERE job_id = 'IT_PROG'
)AND job_id <>'IT_PROG';
3.行子查询(一行多列,多行多列)
SELECT
MIN(employee_id)
FROM
employees;
SELECT
MAX(salary)
FROM
employees;
SELECT
*
FROM
employees
WHERE
employee_id = (
SELECT MIN(employee_id)
FROM employees)AND salary = (SELECT MAX(salary)
FROM employees);
SELECT *
FROM
employees
WHERE (employee_id,salary)=(
SELECT MIN(employee_id),MAX(salary)
FROM employees
);
SELECT d.*,(
SELECT COUNT(*)
FROM employees e
WHERE e.department_id =d.department_id
) 个数
FROM departments d;
SELECT
AVG(salary) ,department_id
FROM
employees
GROUP BY
department_id;
SELECT
ag_dep.*,g.grade_level
FROM (
SELECT AVG(salary) ag,department_id
FROM employees
GROUP BY department_id
) ag_dep
INNER JOIN
job_grades g
ON
ag_dep.ag BETWEEN lowest_sal AND highest_sal;
进阶八:分页查询
SELECT
查询列表
FROM
表
【JOIN type join 表2
ON 连接条件
WHERE 筛选条件
GROUP BY 分组字段
having 分组后筛选
ORDER BY 排序的字段】
limit offset,size;
#offset表示要显示条目的起始索引(从0开始)
#size表示显示的条目个数
SELECT
查询列表
FROM
limit (page-1)*size ,size;
SELECT * FROM employees
LIMIT 0,5;
SELECT * FROM employees
LIMIT 5;
SELECT * FROM employees
LIMIT 10,15;
SELECT *
FROM
employees
WHERE
commission_pct is NOT NULL
ORDER BY
salary DESC
LIMIT 10;
进阶九:联合查询
查询语句1
union
查询语句2
union
...
SELECT *
FROM
employees
WHERE
email LIKE '%a%'
OR
department_id>90;
SELECT * FROM employees WHERE email like '%a%'
UNION
SELECT * FROM employees WHERE department_id>90;
进阶十:DML语言
一、插入语句
insert INTO 表名(列名,...) values(值1,...);
INSERT INTO 表名
set 列名=值,列名=值,...
INSERT INTO beauty
VALUES(18,'畅','男',NULL,'1165654',NULL,NULL);
INSERT INTO beauty
SET id=19,NAME='大哥',phone='456465';
二、修改语句
update
表名s
set
列=新值,列=新值,...
WHERE
筛选条件;
update
表1 别名, 表2 别名
SET
列=值,...
where
连接条件
and
筛选条件;
update
表1 别名
inner|left|right join
表2 别名
on
连接条件
set
列=值,...
where
筛选条件;
UPDATE beauty SET phone = '156456465'
WHERE NAME LIKE '唐%';
UPDATE boys SET boyname='张非',usercp='10'
WHERE id ='2';
UPDATE boys bo
INNER JOIN beauty b ON bo.id = b.boyfriend_id
SET b.phone ='156465465'
WHERE bo.boyName = '张无忌';
UPDATE boys bo
RIGHT JOIN beauty b ON bo.id = b.boyfriend_id
SET b.boyfriend_id = '2'
WHERE b.id is NULL;
3.删除语句
delete 表1的别名,表2的别名
from 表1 别名 ,表2 别名
WHERE 连接条件
AND 筛选条件
DELETE 表1的别名,表2的别名
FROM 表1 别名
INNER|left|right| join 表2 别名 on 连接条件
where 筛选条件
DELETE FROM beauty WHERE phone LIKE '%9';
DELETE b FROM beauty b
INNER JOIN boys bo ON b.boyfriend_id=bo.id
WHERE bo.boyName ='张无忌'
DELETE b,bo
FROM beauty b
JOIN boys bo ON b.boyfriend_id=bo.id
WHERE bo.boyName = '黄晓明'
进阶十一:DDL语言
1.表的创建 ★
create table 表名(
列名 列的类型【(长度) 约束】,
列名 列的类型【(长度) 约束】,
列名 列的类型【(长度) 约束】,
...
列名 列的类型【(长度) 约束】
)
CREATE TABLE if NOT EXISTS book(
id INT,#书的编号
bName VARCHAR(20),#图书名
price DOUBLE,#价格
authorId INT, #图书作者
publishDate DATETIME#出版日期
);
CREATE TABLE author(
Id INT,
au_name VARCHAR(20),
nation VARCHAR(20)
);
2.表的修改
ALTER TABLE book CHANGE COLUMN publishdate pubDate DATETIME;
ALTER TABLE book MODIFY COLUMN pubdate TIMESTAMP;
ALTER TABLE author ADD COLUMN annual DOUBLE;
ALTER TABLE author DROP COLUMN annual;
ALTER TABLE author RENAME TO book_author;
3.表的删除
DROP TABLE IF EXISTS book_author
;DROP DATABASE is EXISTS 旧的库名
CREATE DATABASE 新库名;
DROP TABLE IS EXISTS 旧表名;
CREATE TABLE 新表名();
**4.**表的复制
INSERT INTO author VALUES(1,'村上春树','日本'),
(2,'莫言','中国'),
(3,'冯唐','中国'),
(4,'金庸','中国');
CREATE TABLE copy LIKE author;
CREATE TABLE copy2
SELECT * FROM author;
CREATE TABLE copy3
SELECT id,au_name
FROM author
WHERE nation='中国';
CREATE TABLE copy4
SELECT id,au_name
FROM author
WHERE 1=2;
进阶十二:常见的数据类型
1.整型
CREATE TABLE tab_int(
t1 INT,
t2 INT UNSIGNED
);
INSERT INTO tab_int VALUES (-123456,12456);
2.小数
CREATE TABLE tab_float(
f1 FLOAT(5,2),
f2 DOUBLE(5,2),
f3 DECIMAL(5,2)
);
SELECT * FROM tab_float;
INSERT INTO tab_float VALUES(123.45,123.45,123.45);
INSERT INTO tab_float VALUES(123.456,123.456,123.456);
INSERT INTO tab_float VALUES(123.4,123.4,123.4);
INSERT INTO tab_float VALUES(1523.4,1523.4,1523.45);
#原则:所选择的类型越简单越好
3.字符型
写法
M的意思
特点
空间耗费
效率
char char(M)
最大字符数
固定长度的字符
比较耗费
高
VARCHAR VARCHAR(M)
最大的字符数
可变长度的字符
比较节省
低
4.日期型
字节
范围
时区等的影响
datetime
8
较大1000-9999年
不受
TIMESTAMP
4
较小1970-2038年
受
进阶十三:常见约束
1.添加约束的时机
2.约束的添加分类
CREATE TABLE 表名(
字段名 字段类型 列级约束
字段名 字段类型
表级约束
);
CREATE table stuinfo(
id INT PRIMARY KEY,#主键
stuName VARCHAR(20) NOT NULL ,#非空
gender CHAR(1) CHECK(gender='男'OR gender='女'),#检查性别
seat INT UNIQUE ,#唯一
age INT DEFAULT 18 #默认约束
);
CREATE TABLE major(
id INT PRIMARY key,
majorName VARCHAR(20)
);
【CONSTRAINT 约束名】(可以去掉) 约束类型(字段名)
CREATE table IF NOT EXISTS stuinfo(
id INT PRIMARY KEY,
stuname VARCHAR(20) NOT NULL,
gender CHAR(1),
age INT DEFAULT 18,
seat INT UNIQUE ,
majorid INT,
FOREIGN KEY(majorid) REFERENCES major(id)
);
3.标识列
DROP TABLE IF EXISTS tab_identity;
CREATE TABLE tab_identity(
id INT PRIMARY KEY auto_increment,
NAME VARCHAR(20)
);
ALTER TABLE tab_identity MODIFY COLUMN id INT PRIMARY KEY auto_increment;
ALTER TABLE tab_identity MODIFY COLUMN id INT PRIMARY KEY;
进阶十四:TCL语言 事务控制语言
事务(ACID)的属性:
事务的创建:
1.添加约束的时机
2.约束的添加分类
CREATE TABLE 表名(
字段名 字段类型 列级约束
字段名 字段类型
表级约束
);
CREATE table stuinfo(
id INT PRIMARY KEY,#主键
stuName VARCHAR(20) NOT NULL ,#非空
gender CHAR(1) CHECK(gender='男'OR gender='女'),#检查性别
seat INT UNIQUE ,#唯一
age INT DEFAULT 18 #默认约束
);
CREATE TABLE major(
id INT PRIMARY key,
majorName VARCHAR(20)
);
【CONSTRAINT 约束名】(可以去掉) 约束类型(字段名)
CREATE table IF NOT EXISTS stuinfo(
id INT PRIMARY KEY,
stuname VARCHAR(20) NOT NULL,
gender CHAR(1),
age INT DEFAULT 18,
seat INT UNIQUE ,
majorid INT,
FOREIGN KEY(majorid) REFERENCES major(id)
);
3.标识列
DROP TABLE IF EXISTS tab_identity;
CREATE TABLE tab_identity(
id INT PRIMARY KEY auto_increment,
NAME VARCHAR(20)
);
ALTER TABLE tab_identity MODIFY COLUMN id INT PRIMARY KEY auto_increment;
ALTER TABLE tab_identity MODIFY COLUMN id INT PRIMARY KEY;
进阶十四:TCL语言 事务控制语言
事务(ACID)的属性:
事务的创建:
DELETE 和 TRUNCATE在事务使用时的区别:
SET autocommit = 0;
START TRANSACTION;
DELETE FROM account;
ROLLBACK;
SET autocommit=0;
START TRANSACTION;
TRUNCATE TABLE account;
ROLLBACK;
#SAVEPOINT只搭配rollback使用
SET autocommit=0;
START TRANSACTION;
DELETE FROM account WHERE id=25;
SAVEPOINT a;#设置保存点
DELETE FROM account WHERE id=28;
ROLLBACK TO a;#回滚到保存点处
#最终效果只有id25删掉了28没有删掉
进阶十五:视图
SELECT
stuname,majorname
FROM
stuinfo s
INNER JOIN major m on s.majorid=m.id
WHERE
s.stuname like '张%';
CREATE VIEW v1
AS
SELECT
stunname,majorname
FROM
stuinfo s
INNER JOIN major m on s.majorid=m.id;
SELECT * FROM v1
WHERE
s.stuname like '张%';
#注意:为什么使用*,因为视图中就只有一开始指定好的信息
1.如何创建视图?
语法:
SELECT VIEW 视图名
AS
查询语句;
#1.创建
CREATE VIEW myv1
AS
SELECT last_name,department_name,job_title
FROM employees e
JOIN departments d ON e.department_id=d.department_id
JOIN jobs j on j.job_id= e.job_id;
#2.使用
SELECT * FROM myv1 WHERE last_name like '%a%';
#创建视图查看每个部门的平均工资
CREATE VIEW myv2
AS
SELECT AVG(salary) ag,department_id
FROM employees
GROUP BY department_id;
#使用
SELECT myv2.ag,g.grade_level
FROM myv2
JOIN job_grades g
ON myv2.ag BETWEEN g.lowest_sal AND g.highest_sal;
SELECT * FROM myv2
ORDER BY ag
LIMIT 1;
CREATE VIEW myv3
AS
SELECT * FROM myv2 ORDER BY ag LIMIT 1;
SELECT d.*,m.ag
FROM myv3 m
JOIN departments d
on m.department_id = d.department_id;
2.视图的修改
#方式一:
CREATE or REPLACE view 视图名
as
查询语句;
#例:
CREATE OR REPLACE VIEW myv3
AS
SELECT AVG(salary),job_id
FROM employees
GROUP BY job_id;
#方式二:
#语法:
ALTER view 视图名
AS
查询语句;
#例:
ALTER view myv3
AS
SELECT * FROM employees;
3.删除视图
语法:drop VIEW 视图名,视图名,...;
DROP view myv1,myv2;
4.查看视图
SHOW CREATE view myv3;
5.视图的更新
CREATE OR REPLACE VIEW myv1
AS
SELECT last_name,email
FROM employees;
#1.插入
INSERT INTO myv1 VALUES('张飞','[email protected]');
#注意:这里的修改视图会影响到原来的表的内容
#2.修改
UPDATE myv1 SET last_name ='张无忌' WHERE last_name='张飞';
#3.删除
DELETE FROM myv1 WHERE last_name ='张无忌';
视图和表的对比
是否占用物理空间
使用
视图:CREATE view
没有(仅仅保存了逻辑,没有保留数据)
增删改查,一般不能增删改
表:CREATE TABLE 占用
占用
增删改查
进阶十六:变量
1、系统变量
SHOW GLOBAL |【session】 VARIABLES;
SHOW GLOBAL|【SESSION】 VARIABLES like '%char%';
SELECT @@global|【SESSION】.系统变量名
set GLOBAL |【session】 系统变量名 = 值;
set @@GLOBAL |【session】.系统变量名 =值;
全局变量:
SHOW GLOBAL VARIABLES;
SHOW GLOBAL VARIABLES LIKE '%CHAR%';
SELECT @@global.autocommit;
SELECT @@tx_isolation;
SET @@global.autocommit=0;
会话变量:
SHOW VARIABLES;
SHOW VARIABLES LIKE '%CHAR%';
SHOW SESSION VARIABLES LIKE '%CHAR%';
SELECT @@session.tx_isolation;
SELECT @@tx_isolation;
SET @@session.tx_isolation='read-UNCOMMITTED';
SET SESSION tx_isolation = 'read-COMMITTED';
2、自定义变量
用户变量
SET @用户变量名 =值;
SET @用户变量名:=值;
SELECT @用户变量名:=值;
SET @用户变量名 =值;
SET @用户变量名:=值;
SELECT @用户变量名:=值;
SET @name = 'john';
SET @name=100;
SELECT 字段名 INTO 变量名
FROM 表;
SET @count =1
SELECT COUNT(*) INTO @count
FROM employees;
SELECT @用户变量名;
SELECT @count;
局部变量
DECLARE 变量名 类型;
DECLARE 变量名 类型 DEFAULT 值;
set 局部变量名=值;
set 局部变量名:=值;
SELECT @局部变量名:=值;
SELECT 字段 into 局部变量名
FROM 表;
SELECT 局部变量名;
作用域
定义和使用的位置
语法
用户变量
当前会话
会话中的任何地方
必须加@符号,不用限定类型
局部变量
begin END中
只能在begin end中,且为第一句话
一般不用加@符号,需要限定类型
SET @m=1;
SET @n=2;
SET @sum=@m+@n;
SELECT @sum;
DECLARE m INT DEFAULT 1;
DECLARE n INT DEFAULT 2;
DELETE sum INT;
SET sum=m+n;
SELECT sum;
进阶十七:存储过程和函数
存储过程
1:创建语法
CREATE PROCEDURE 存储过程名(参数列表)
BEGIN
存储过程体(一组合法的SQL语句)
END
2:调用语法
CALL 存储过程名(实参列表);
SELECT * FROM admin;
delimiter $
CREATE PROCEDURE myp1()
BEGIN
INSERT INTO admin(username,`password`)
VALUES('john1','156456'),('lily','0000'),('jvaad','56465'),('dasd','465465'),('4dasd','41324');
END $
delimiter $
CREATE PROCEDURE myp2(IN beautyName VARCHAR(20))
BEGIN
SELECT bo.*
FROM boys bo
RIGHT JOIN beauty b ON bo.id = b.boyfriend_id
WHERE b.name = beautyName;
END $
#调用
delimiter $
CALL myp2('柳岩')$
delimiter $
CREATE PROCEDURE myp3(in username VARCHAR(20),IN PASSWORD VARCHAR(20))
BEGIN
DECLARE result INT DEFAULT 0;#声明并初始化
SELECT COUNT(*) INTO result;#赋值
FROM admin
WHERE admin.username=username
AND admin.password=password;
SELECT IF(rusult>0,'成功','失败');#使用
end $
delimiter $
USE girls
CREATE PROCEDURE myp4(in beautyName VARCHAR(20),OUT boyName VARCHAR(20))
BEGIN
SELECT bo.boyName
FROM boys bo
INNER JOIN beauty b ON bo.id=b.boyfriend_id
WHERE b.name=beautyName;
END $
#调用:
delimiter $
CALL myp4('王语嫣',@bname)$
SELECT @bname$
delimiter $
CREATE PROCEDURE myp5(in beautyName VARCHAR(20),OUT boyName VARCHAR(20),OUT userCP INT)
BEGIN
SELECT bo.boyName,bo.userCP INTO boyName,userCP
FROM boys bo
INNER JOIN beauty b ON bo.id=b.boyfriend_id
WHERE b.name=beautyName;
END $
#调用
CALL myp5('王语嫣',@bname,@usercp);
SELECT @bname,@usercp$
delimiter $
CREATE PROCEDURE myp3(INOUT a INT,INOUT b INT)
BEGIN
SET a = a*2;
SET b = b*2;
END $
#调用
delimiter $
SET @m=10$
SET @n=20$
CALL myp3(@m,@n)$
SELECT @m,@n$
delimiter $
CREATE PROCEDURE test1 (IN username VARCHAR(20),IN loginPwd VARCHAR(20))
BEGIN
INSERT INTO admin(admin.username,PASSWORD)
VALUES(username,loginPwd);
END$
delimiter $
CREATE PROCEDURE test2(IN id INT,OUT name VARCHAR(20),OUT phone VARCHAR(20))
BEGIN
SELECT b.name ,b.phone INTO NAME ,phone
FROM beauty b
WHERE b.id=id;
END $
delimiter $
CREATE PROCEDURE test3(IN birth1 datetime,IN birth2 datetime,out result INT)
BEGIN
SELECT DATEDIFF(birth1,birth2) INTO result;
END $
3.删除存储过程
DROP PROCEDURE p1;
DROP PROCEDURE p2,p3;#不可以! 只可以放一个
4.查看存储过程的信息
SHOW CREATE PROCEDURE myp2;
函数
1.函数创建语法
CREATE FUNCTION 函数名(参数列表) RETURNS 返回类型
BEGIN
函数体
END
2.调用语句
SELECT 函数名(参数列表)
SET GLOBAL = TRUE;
delimiter $
USE myemployees;
CREATE FUNCTION myf1() RETURNS INT
BEGIN
DECLARE c INT DEFAULT 0;
SELECT count(*) INTO c
FROM employees;
RETURN c;
END $
SELECT myf1()$
CREATE FUNCTION myf2(empName VARCHAR(20)) RETURNS DOUBLE
BEGIN
SET @sal=0;#定义用户变量
SELECT salary INTO @sal #赋值
FROM employees
WHERE last_name = empName;
RETURN @sal;
END $
SELECT myf2('k_ing')$
CREATE FUNCTION myf3(deptName VARCHAR(20)) RETURNS DOUBLE
BEGIN
DECLARE sal DOUBLE;
SELECT AVG(salary) INTO sal
FROM employees e
JOIN departments d ON e.department_id=d.department_id
WHERE d.department_name = deptName;
RETURN sal;
END$
SELECT myf3('IT')$
3.函数的查看
SHOW CREATE FUNCTION myf3;
4.函数的删除
DROP FUNCTION myf3;
delimiter $
CREATE FUNCTION test4(num1 FLOAT ,num2 FLOAT) RETURNS FLOAT
BEGIN
DECLARE sum FLOAT DEFAULT 0;
SET sum=num1+num2;
RETURN sum;
end$
SELECT test4(1,2)$
进阶十八:流程控制结构
1.分支结构
IF(表达式1,表达式2,表达式3)
执行顺序:
如果表达式1成立,则返回2值,否则返回3值。
CASE 变量|表达式|字段
WHEN 要判断的值 THEN 返回的值1或语句n1;
WHEN 要判断的值 THEN 返回的值2或语句n2;
...
ELSE 要返回的值或者语句n;
end CASE;
CASE
WHEN 要判断的条件1 THEN 返回的值1或语句n1;
WHEN 要判断的条件2 THEN 返回的值2或语句n2;
...
ELSE 要返回的值或语句n
end CASE;
if 条件1 then 语句1;
ELSEIF 条件2 then 语句2;
...
【else 语句n;】
END IF;
2.循环结构:
【标签:】while循环条件 do
循环体;
end WHILE 【标签】;
【标签:】LOOP
循环体;
end LOOP 【标签】;
#可以用来模拟简单的死循环
【标签:】repeat
循环体;
UNTIL 结束循环的条件
end REPEAT 【标签】;
delimiter $
DROP PROCEDURE pro_while1$
delimiter $
CREATE PROCEDURE pro_while1(IN insertCount INT)
BEGIN
DECLARE i INT DEFAULT 1;
WHILE i<=insertCount DO
INSERT INTO admin(username,PASSWORD) VALUES(CONCAT('rose',i),'666');
SET i=i+1;
END WHILE;
END $
delimiter $
CALL pro_while1(100)$
SELECT * FROM admin$
TRUNCATE TABLE admin$
DROP PROCEDURE test_while1$
delimiter $
CREATE PROCEDURE test_while1(IN insertCount INT)
BEGIN
DECLARE i INT DEFAULT 1;
a:WHILE i<=insertCount DO
INSERT INTO admin(username,PASSWORD) VALUES(CONCAT('re',i),'666');
IF i>=20 THEN LEAVE a;
END IF;
SET i=i+1;
END WHILE a;
END$
delimiter $
CALL test_while1(50)$
SELECT * FROM admin$
4.查看存储过程的信息
SHOW CREATE PROCEDURE myp2;
函数
1.函数创建语法
CREATE FUNCTION 函数名(参数列表) RETURNS 返回类型
BEGIN
函数体
END
2.调用语句
SELECT 函数名(参数列表)
SET GLOBAL = TRUE;
delimiter $
USE myemployees;
CREATE FUNCTION myf1() RETURNS INT
BEGIN
DECLARE c INT DEFAULT 0;
SELECT count(*) INTO c
FROM employees;
RETURN c;
END $
SELECT myf1()$
CREATE FUNCTION myf2(empName VARCHAR(20)) RETURNS DOUBLE
BEGIN
SET @sal=0;#定义用户变量
SELECT salary INTO @sal #赋值
FROM employees
WHERE last_name = empName;
RETURN @sal;
END $
SELECT myf2('k_ing')$
CREATE FUNCTION myf3(deptName VARCHAR(20)) RETURNS DOUBLE
BEGIN
DECLARE sal DOUBLE;
SELECT AVG(salary) INTO sal
FROM employees e
JOIN departments d ON e.department_id=d.department_id
WHERE d.department_name = deptName;
RETURN sal;
END$
SELECT myf3('IT')$
3.函数的查看
SHOW CREATE FUNCTION myf3;
4.函数的删除
DROP FUNCTION myf3;
delimiter $
CREATE FUNCTION test4(num1 FLOAT ,num2 FLOAT) RETURNS FLOAT
BEGIN
DECLARE sum FLOAT DEFAULT 0;
SET sum=num1+num2;
RETURN sum;
end$
SELECT test4(1,2)$
进阶十八:流程控制结构
1.分支结构
IF(表达式1,表达式2,表达式3)
执行顺序:
如果表达式1成立,则返回2值,否则返回3值。
CASE 变量|表达式|字段
WHEN 要判断的值 THEN 返回的值1或语句n1;
WHEN 要判断的值 THEN 返回的值2或语句n2;
...
ELSE 要返回的值或者语句n;
end CASE;
CASE
WHEN 要判断的条件1 THEN 返回的值1或语句n1;
WHEN 要判断的条件2 THEN 返回的值2或语句n2;
...
ELSE 要返回的值或语句n
end CASE;
if 条件1 then 语句1;
ELSEIF 条件2 then 语句2;
...
【else 语句n;】
END IF;
2.循环结构:
【标签:】while循环条件 do
循环体;
end WHILE 【标签】;
【标签:】LOOP
循环体;
end LOOP 【标签】;
#可以用来模拟简单的死循环
【标签:】repeat
循环体;
UNTIL 结束循环的条件
end REPEAT 【标签】;
delimiter $
DROP PROCEDURE pro_while1$
delimiter $
CREATE PROCEDURE pro_while1(IN insertCount INT)
BEGIN
DECLARE i INT DEFAULT 1;
WHILE i<=insertCount DO
INSERT INTO admin(username,PASSWORD) VALUES(CONCAT('rose',i),'666');
SET i=i+1;
END WHILE;
END $
delimiter $
CALL pro_while1(100)$
SELECT * FROM admin$
TRUNCATE TABLE admin$
DROP PROCEDURE test_while1$
delimiter $
CREATE PROCEDURE test_while1(IN insertCount INT)
BEGIN
DECLARE i INT DEFAULT 1;
a:WHILE i<=insertCount DO
INSERT INTO admin(username,PASSWORD) VALUES(CONCAT('re',i),'666');
IF i>=20 THEN LEAVE a;
END IF;
SET i=i+1;
END WHILE a;
END$
delimiter $
CALL test_while1(50)$
SELECT * FROM admin$