10.约束是可以删除的
删除约束之后,表与表之间的关系消失,然后可以把外键对应的主键删除
11.主键
定义:能够唯一标识一个实体的一个字段或者多个字段的组合
附注:
1.含有主键的表叫作主键表
2.主键通常都是整数,不建议使用字符串当做主键
如果主键用于集群式服务,才可以考了用字符串当主键
3.主键的值通常都不允许修改,除非本记录被删除
4.主键的命名要定义成:表名_id
5.要用代理主键,不要用业务主键
我们通常都是在表中单独添加一个整型的编号充当主键字段
12.外键
另外一张表,或另外几张表的主键或唯一键
附注:
1.外键通常是来自另外表的主键而不是唯一键,因为唯一键可能是null
2.外键不一定来自另外的表,也可能是本表的主键
3.含有外键的表叫外键表,外键字段来自的那张表叫作主键表
问题:先删外键表还是主键表
先删外键表
如果先删主键表,会报错,因为这会导致外键表中的数据引用失败
13.查询【最重要的,数据库中的最重要的操作】
1.计算列
1.查询列:select ename,sal from emp;
2.计算列:select ename,sal*12 as "年薪" from emp;
注意这里的年薪是加上英文双引号的
3.查询常量:select 5 from emp;
语法是正确的
输出的行数是emp表的行数,每行只有一个字段,值是5
** select 5;
也是正确的,但是只输出一行,这一行只有一个字段,值是5
注意:
Oracle中字段的别名不允许用单引号括起来,只能使用双引号括起来
SQLServer却允许使用单引号或者双引号
因此,为了兼容性,最好字段别名使用双引号括起来
2.distinct【不允许重复的】
select deptno from emp;
查询出来14条记录,不是3条
select distinct deptno from emp;
distinct deptno会过滤重复的deptno
select distinct comm from emp;
distinct也可以过滤掉重复的null
select distinct comm,deptno from emp;
把comm和deptno的组合进行过滤
select deptno,distinct comm from emp;
逻辑上有冲突,error
3.between
1.情况1:
select* from emp
where sal between 1500 and 3000;
等价于:
select *from emp
where sal>=1500 and sal<=3000;
2.情况2:【not】
select* from emp
where sal not between 1500 and 3000;
等价于:
select *from emp
where sal<1500 or sal>3000;
4.in【某一属性属于若干个孤立的值组成的集合】
情况1:
select * from emp
where sal in(1500,3000,5000);
等价于:
select *from emp
where sal=1500 or sal=3000 or sal=5000;
情况2:【not】
select * from emp
where sal not in(1500,3000,5000);
等价于:
select *from emp
where sal!=1500 and sal=3000 and sal=5000;
***数据库中的不等于有两种:!=和<> 推荐第二种
5.top
1.select top 2 * from emp;
选出emp表中的前2行数据
2.select top 15 percent * from emp;
选出emp表中前 行总数的15%行的数据,向上取整,例如:2.1个是3个
3.SQLServer使用【top】来分页
Oracle使用【rownum】来分页
4.select top 5 from emp;
报错
6.null【没有值,空值】
输出奖金非空的员工的信息
1.error:select * from emp where comm <> null;
输出为空,没有报错,但与事实不符,
2.error:select * from emp where comm != null;
输出为空,没有报错,但与事实不符,
3.right:select * from emp where comm is not null;
4.总结
1.null不能参与<>,!=,<,>,<=,>=,=,+,-,*,/等运算
但是可以参与is和is not运算
2.任何类型的数值都允许是null
3.任何数字与null参与数学运算的结果永远都是null
5.isnull()函数
1.计算年薪的方法
select ename,sal*12+isnull(comm,0) as "年薪"from emp;
2.isnull(comm,0)的意思
如果comm为null,则返回0,否则返回原comm值
7.order by
1.把工资在1500到3000之间(包括上下边界)的员工中
工资最高的4个人的信息按降序输出
select top 4 *
from emp
where sal between 1500 and 3000
order by sal desc;
代码执行顺序:先执行from,然后找出1500<=sal<=3000的数据
然后,进行降序排序,最后取出前4个;
2.desc:降序
asc:升序,默认值是asc
3.多个属性组合排序
select * from emp order by deptno,sal;
先按照deptno升序排序,再按照sal升序排序【默认升序排序】
select * from emp order by deptno desc,sal;
先按照deptno降序排序,再按照sal升序排序
8.模糊查询
1.示例代码
1.ename只要含有A就输出
select * from emp
where ename like '%A%';
2.ename只要首字母是A就输出
select * from emp
where ename like 'A%';
3.ename只要尾字母是A就输出
select * from emp
where ename like '%A';
4.ename只要第二个字母是A就输出
select * from emp
where ename like '_A%';
2.格式:
select 字段的集合 from 表名 where 某个字段的名字 like 匹配条件
匹配条件通常含有通配符,匹配条件必须使用单引号括起来
3.通配符
1.%:
表示任意0个或多个字符
2.下划线_:
表示任意单个字符
3.[a-f]:
表示a-f中的任意单个字符
4.[a,f]:
a或f
5.[^a-c]:
不是a-f中的任意单个字符
4.使用转义字符
select * from student where name like '%\%%' escape '\';
1.escape '\'表示把'\'字符当做转义字符的标志
2.在sql中可以把任意字符当做转义字符的标志,具体是把哪个字符当做转移字符,
这由escape后面跟着的字符决定
9.聚合函数【多行记录返回一个值,通常用于统计分组的信息】
1.函数的分类
1.单行函数
每行返回一个值
2.多行函数
多行返回一个值
3.示例
1.select lower(ename)from emp;
最终返回的是14行,lower()是单行函数
2.select max(sal) from emp;
返回1行,max()是多行函数
2.常见聚合函数
1.max()
2.min()
3.avg() 平均值
4.count()
1.select count(*) from emp;
返回emp表所有记录的个数
2.select count(deptno) from emp;
返回deptno的个数,重复值也计数
3.select count(distinct deptno) from emp;
不记录重复值
4.select count(comm) from emp;
返回值是4,不记录空值,只记录非空值
5.判断如下sql语句是否正?
select max(sal),min(sal),count(*) from emp; --正确
select max(sal) "最高工资",min(sal) "最低工资",count(*) "员工人数" from emp; --正确
select max(sal),lower(ename) from emp; --错误
10.group by
**补充:use 库名; --表示后面的操作都是在库名对应的数据库中进行的
1.输出每个部门的编号和该部门的平均工资
select deptno,avg(sal) as "部门平均工资"
from emp;
group by deptno;
2.判断下面语句是否正确
select deptno,ename
from emp
group by deptno;
错误,只能选中分组内部的信息,不能选择分组以外的信息,ename就是部门以外的信息
3.总结
使用group by之后select中只能出现分组后的整体信息,不能出现组内的详细信息
4.组合分组
select deptno,job,avg(sal) "平均值",count(*)"分组成员数",sum(sal)"总工资",min(sal)"最小工资"
from emp
group by deptno,job;
5.功能:
把表中的记录按照字段分成不同的组
6.空值也可以当成一组
11.having【对分组之后的信息进行过滤】
1.输出部门平均工资大于1500的部门编号 部门的平均工资
2.having和where的区别
where对分组之前的信息进行过滤
having对分组之后的信息进行过滤
having和where一样,子句中不能出现字段的别名
**补充:into的用法
select * into emp_1 from emp where dept=10;
新建一张表,把查询结果存放在里面
12.连接查询
1.定义
将两个或两个以上的表以一定的连接条件连接起来,从中检索满足条件的数据。
2.分类
1.内连接【重点】
1.select ... from A,B;的用法【无连接条件】
表A和B做笛卡尔积
示例:select * from emp,dept;
一共70行,14*5=70,emp是14行,dept是5行,emp和dept做笛卡尔积
2.select ... from A,B where ... ;的用法【有连接条件】
对多个表做笛卡尔积之后的结果进行过滤,where后面的是连接条件
示例:select * from emp,dept where emp.deptno=dept.deptno;
3.select ... from A join B on ... ;的用法
有join就必须有on
示例:
select "E".ename "员工姓名","D".dname "部门名称"
from emp "E"
join dept "D" --join是连接
on "E".deptno="D".deptno; --on后面的是连接条件
4.select ... from A,B where ...;与 select ... from A join B on ... ;可以等价转换
1.select ... from A,B where ...;是SQL92标准
2.select ... from A join B on ... ;是SQL99标准
推荐使用SQL99标准
在SQL99标准中,on和where可以做不同的分工
1.on指连接条件
2.where对连接之后临时表的数据进行过滤,where只能写在join on的后面
3.顺序可以理解为:先根据on的连接条件连接,连接之后再根据where的过滤条件过滤
3.把工资大于2000的员工的姓名和部门的编号输出
1.92标准实现
select*from emp,dept
where emp.sal>2000--过滤条件and emp.deptno=dept.deptno;--连接条件
2.99标准实现
select*from emp
join dept on emp.deptno=dept.deptno --连接条件where emp.sal>2000;--过滤条件
4.select * from emp,dept where dept.deptno=10;使用SQL99标准如何实现
select * from emp join dept on 1=1 where dept.deptno=10;
5.select、from、where、join、on、group、order、top、having的混合使用
selecttop...from A
join B
on...join C
on...wheregroupby...having...orderby...
6.习题
1.求出每个员工的姓名、部门编号、薪水和薪水等级
select ename,deptno,sal,grade
from emp "E"join SALGRADE "SAL"on"E".sal<="SAL".HISAL and"E".sal>="SAL".LOSAL
3.求出emp表中所有领导的姓名
1.答案1:
select ename
from(select distinct mgr from emp) "T"
join emp
on "T".mgr=emp.EMPNO;
2.答案2:
select ename
from emp
where empno in (select mgr from emp);
3.思考题:求出emp表中非领导的姓名
select ename
from emp
where empno not in (select mgr from emp where mgr is not null);
**这里要思考in和null组合时,虽然不会报错,但是输出的结果与事实不符
4.求出平均薪水最高的部门的编号和部门的平均工资
selecttop3 ename,"T".deptno,dname,GRADE
from(select ename,empno,deptno,sal
from emp
where emp.EMPNO=(select empno from emp where sal>(selectmin(sal)from emp)).EMPNO)"T"--筛选条件join dept on dept.deptno="T".deptno --连接条件join SALGRADE on"T".sal<=SALGRADE.HISAL and"T".sal>=LOSAL --连接条件orderby sal desc;