1.sql简介
结构化查询语言(Structured Query Language)简称SQL(发音:/ˈɛs kjuː ˈɛl/ "S-Q-L"),结构化查询语言是一种数据库查询和程序设计语言,用于存取数据以及查询、更新和管理关系数据库系统;同时也是数据库脚本文件的扩展名。结构化查询语言是高级的非过程化编程语言,允许用户在高层数据结构上工作。它不要求用户指定对数据的存放方法,也不需要用户了解具体的数据存放方式,所以具有完全不同底层结构的不同数据库系统, 可以使用相同的结构化查询语言作为数据输入与管理的接口。结构化查询语言语句可以嵌套,这使它具有极大的灵活性和强大的功能。
-
DML(数据库操作语言): 其语句包括动词INSERT,UPDATE和DELETE。它们分别用于添加,修改和删除表中的行。也称为动作查询语言。
-
DDL(数据库定义语言): 其语句包括动词CREATE和DROP。在数据库中创建新表或删除表(CREAT TABLE 或 DROP TABLE);为表加入索引等。DDL包括许多与人数据库目录中获得数据有关的保留字。它也是动作查询的一部分。
-
DCL(数据库控制语言):它的语句通过GRANT或REVOKE获得许可,确定单个用户和用户组对数据库对象的访问。某些RDBMS可用GRANT或REVOKE控制对表单个列的访问。
2.简单查询
1.查询语法
Select * |列名 from 表名
2.别名用法
在查询的结果列中可以使用别名
Select 列名 别名,列名别名,... from emp;
3.删除重复的数据
Select distinct *|列名, ... from emp;
使用distinct可以消除重复的行,如果查询多列的必须保证多列都重复才能去掉重复
4.字符串连接查询
查询雇员编号,姓名,工作
编号是:7369的雇员, 姓名是:smith,工作是:clerk
字符串的连接使用‘||’
5.查询中四则运算
查询每个雇员的年薪
Select ename, sal*12 from emp;
Select ename, sal*12 income from emp;
Sql中支持四则运算“+,-,*,/”
3.限定查询
在查询绝大多数都会有条件的限制
语法:select *|列名 from 表名 where 条件
例如:查询工资大于1500的所有雇员
1.非空和空的限制
- 示例:查询每月能得到奖金的雇员
- 分析:只要字段中存在内容表示不为空,如果不存在内容就是null,
- 语法:列名 IS NOT NULL
- 为空 列名 IS NULL
- 范例:查询工资大于1500并且有奖金领取的雇员
- 分析:多个查询条件同时满足之间使用‘AND’
- 范例:查询工资大于1500或者有奖金的雇员
- 分析:多个查询条件或满足,条件之间使用“OR”
- 范例:查询工资不大于1500和没有奖金的人
- 语法:NOT(查询条件)
- 范例:基本工资大于1500但是小于3000的全部雇员
- 分析:sal>1500, sal<3000
- Between and等于 sal > =1500 and sal <= 3000
- 范例:查询1981-1-1到1981-12-31号入职的雇员
- 分析:between and 不仅可以使用在数值之间,也可以用在日期的区间
- 范例:查询雇员名字叫smith的雇员
- 在oracle中的查询条件中查询条件的值是区分大小写的
- 范例:查询雇员编号是7369,7499,7521的雇员编号的具体信息
- 如果使用之前的做法可以使用OR关键字
- 实际上,此时指定了查询范围,那么sql可以使用IN关键字
- 语法: 列名 IN (值1,值2,....)
- 列名 NOT IN (值1, 值2,...)
- 其中的值不仅可以是数值类型也可以是字符串
- 在常用的站点中经常会有模糊查询,即:输入一个关键字,把符合的内容全部的查询出来,在sql中使用LIKE语句完成。
- 在LIKE中主要使用以下两种通配符
- “%”:可以匹配任意长度的内容
- “_”:可以匹配一个长度的内容
- 范例:查询出所有雇员姓名中第二个字符包含“M”的雇员
- 在LIKE中如果没有关键字表示查询全部
- 查询名字中带有“M”的雇员
- 在oracle中不等号的用法可以有两种形式“<>”和“!=”
- 范例:查询雇员编号不是7369的雇员信息
4.对结果集排序
在sql中可以使用ORDER BY对查询结果进行排序
语法:SELECT * |列名 FROM 表名 {WEHRE 查询条件} ORDER BY 列名1 ASC|DESC,列名2...ASC|DESC
范例:查询雇员的工资从低到高
分析:ORDER BY 列名 默认的排序规则是升序排列,可以不指定ASC,如果按着降序排列必须指定DESC
- 如果存在多个排序字段可以用逗号分隔
注意ORDER BY语句要放在sql的最后执行。
5.单行函数
1.字符函数
接收字符输入返回字符或者数值,dual是伪表
- 把小写的字符转换成大小的字符
upper('smith')
- 把大写字符变成小写字符
lower('SMITH')
- 把首字符大写
initcap('smith')
- 字符串的连接可以使用concat可以使用“||”建议使用“||”
concat('hello', 'world')
- 字符串的截取,使用substr,第一个参数是源字符串,第二个参数是开始索引,第三个参数结束的索引,开始的索引使用1和0效果相同
substr('hello', 1,3)
- 获取字符串的长度
length('hello')
- 字符串替换,第一个参数是源字符串,第二个参数被替换的字符串,第三个是替换字符串
replace('hello', 'l','x')
2.数值函数
- 四舍五入函数:ROUND()
默认情况下ROUND四舍五入取整,可以自己指定保留的位数。
- 取整:TRUNC(),默认全部去掉小数,也可以指定保留的位数
- 取余数MOD()
3.日期函数
Oracle中提供了很多和日期相关的函数,包括日期的加减,在日期加减时有一些规律
日期 – 数字 = 日期
日期 + 数字 = 日期
日期 – 日期 = 数字(天)
- 范例:查询雇员的进入公司的周数。
- 分析:查询雇员进入公司的天数(sysdate – 入职日期)/7就是周数
- 获得两个时间段中的月数:MONTHS_BETWEEN()
- 范例:查询所有雇员进入公司的月数
- 获得几个月后的日期:ADD_MONTH()
- 范例:求出三个月后的日期
- 指定给出下次某日期数NEXT_DATE()
- 范例:求出下一个星期一是什么日期
- 求出一个日期的最后一天
- 范例:求出本月的最后一天是几号
4.转换函数
- TO_CHAR:字符串转换函数
- 范例:查询所有的雇员将将年月日分开,此时可以使用TO_CHAR函数来拆分
- 拆分时需要使用通配符
- 年:y, 年是四位使用yyyy
- 月:m, 月是两位使用mm
- 日:d, 日是两位使用dd
- 时:HH是12进制,HH24进制
- 分:mi
- 秒:ss
在结果中10以下的月前面被被补了前导零,可以使用fm去掉前导零
TO_CHAR还可以给数字做格式化
- 范例:把雇员的工资按三位用“,”分隔,在oracle中“9”代表一位数字
如果在钱的前面加上国家的符号可以使用“$”代表是美元,如果要使用本地的钱的单位使用“L”
- TO_NUMBER:数值转换函数
- TO_NUMBER可以把字符串转换成数值
- TO_DATE:日期转换函数
- TO_DATE可以把字符串的数据转换成日期类型
5.通用函数
- 空值处理nvl
- 范例:查询所有的雇员的年薪
我们发现很多员工的年薪是空的,原因是很多员工的奖金是null,null和任何数值计算都是null,这时我们可以使用nvl来处理。
- Decode函数
- 该函数类似if....else if...esle
- 语法:DECODE(col/expression, [search1,result1],[search2, result2]....[default])
- Col/expression:列名或表达式
- Search1,search2...:用于比较的条件
- Result1, result2...:返回值
- 如果col/expression和Searchi匹配就返回resulti,否则返回default的默认值
- 范例:查询出所有雇员的职位的中文名
- case when
CASE WHEN comparison_expr1 THEN return_expr1
[WHEN comparison_expr2 THEN return_expr2
WHEN comparison_exprn THEN return_exprn
ELSE else_expr]
END
select t.empno,
t.ename,
case
when t.job = 'CLERK' then
'业务员'
when t.job = 'MANAGER' then
'经理'
when t.job = 'ANALYST' then
'分析员'
when t.job = 'PRESIDENT' then
'总裁'
when t.job = 'SALESMAN' then
'销售'
else
'无业'
end
from emp t
6.多表查询
1.多表连接基本查询
使用一张以上的表做查询就是多表查询
语法: SELECT {DISTINCT} *|列名.. FROM 表名 别名,表名1 别名 {WHERE 限制条件 ORDER BY 排序字段 ASC|DESC...}
范例:查询员工表和部门表
- 我们发现产生的记录数是56条,我们还会发现emp表是16条,dept表是4条,56正是emp表和dept表的记录数的乘积,我们称其为笛卡尔积。
- 如果多张表进行一起查询而且每张表的数据很大的话笛卡尔积就会变得非常大,对性能造成影响,想要去掉笛卡尔积我们需要关联查询。
- 在两张表中我们发现有一个共同的字段是depno,depno就是两张表的关联的字段,我们可以使用这个字段来做限制条件,两张表的关联查询字段一般是其中一张表的主键,另一张表的外键。
关联之后我们发现数据条数是14条,不在是56条。
多表查询我们可以为每一张表起一个别名
范例:查询出雇员的编号,姓名,部门的编号和名称,地址
范例:查询出每个员工的上级领导
分析:emp表中的mgr字段是当前雇员的上级领导的编号,所以该字段对emp表产生了自身关联,可以使用mgr字段和empno来关联
范例:在上一个例子的基础上查询该员工的部门名称
分析:只要在上一个例子基础上再加一张表的关联,使用deptno来做关联字段即可
范例:查询出每个员工编号,姓名,部门名称,工资等级和他的上级领导的姓名,工资等级
select e.empno,
e.ename,
decode(s.grade,
1,'一级',
2,'二级',
3,'三级',
4,'四级',
5,'五级') grade,
d.dname,
e1.empno,
e1.ename,
decode(s1.grade,
1,'一级',
2,'二级',
3,'三级',
4,'四级',
5,'五级') grade
from emp e, emp e1, dept d, salgrade s, salgrade s1
where e.mgr = e1.empno
and e.deptno = d.deptno
and e.sal between s.losal and s.hisal
and e1.sal between s1.losal and s1.hisal
2.外连接(左右连接)
- 右连接
当我们在做基本连接查询的时候,查询出所有的部门下的员工,我们发现编号为40的部门下没有员工,但是要求把该部门也展示出来,我们发现上面的基本查询是办不到的
使用(+)表示左连接或者右连接,当(+)在左边表的关联条件字段上时是左连接,如果是在右边表的关联条件字段上就是右连接。
范例:查询出所有员工的上级领导
分析:我们发现使用我们以前的做法发现KING的上级领导没有被展示,我们需要使用左右连接把他查询出来
3.sql1999对SQL的支持
- 交叉连接CROSS JOIN(了解)
交叉连接会产生笛卡尔积
- 自然连接NATURAL JOIN(了解)
自然连接会自动的分析管理条件进行连接,去掉笛卡尔积。
- USING子句,直接管理操作(了解)
- ON子句,自己编写连接条件(重要)
On相当于where
- 左连接和右连接LEFT JOIN和RIGHT JOIN(重要)
4.分组函数
- 统计记录数count()
范例:查询出所有员工的记录数
不建议使用count(*),可以使用一个具体的列以免影响性能
- 最小值查询min()
范例:查询出来员工最低工资
- 最大值查询max()
范例:查询出员工的最高工资
4.查询平均值avg()
范例:查询出员工的平均工资
5.求和函数sum()
范例:查询出20部门的员工的工资总和
5.分组统计
分组统计需要使用GROUP BY来分组
语法:SELECT * |列名 FROM 表名 {WEHRE 查询条件} {GROUP BY 分组字段,分组字段1,…} ORDER BY 列名1 ASC|DESC,列名2...ASC|DESC
范例:查询每个部门的人数
范例:查询出每个部门的平均工资
如果我们想查询出来部门编号,和部门下的人数
我们发现报了一个ORA-00937的错误
注意:
- 如果使用分组函数,SQL只可以把GOURP BY分组条件字段和分组函数查询出来,不能有其他字段。
- 如果使用分组函数,不使用GROUP BY 只可以查询出来分组函数的值
范例:按部门分组,查询出部门名称和部门的员工数量
范例:查询出部门人数大于5人的部门
分析:需要给count(ename)加条件,此时在本查询中不能使用where,可以使用HAVING在group by后面作用在分组函数上
范例:查询出部门平均工资大于2000的部门
范例:显示非销售人员工作名称以及从事同一工作的员工的月工资的总和,并且要满足从事同一工作月工资总和大于5000,结果按月工资总和的升序排列。
分析:
-
查询出非销售人员
-
以步骤1为基础按着工作分组求工资的总和
-
以步骤2为基础查询出月工资总和大于5000的工作
-
按着月工资的总和的升序排列
注意:只有分组条件在结果集中是重复的分组才有意义。
7.子查询
子查询:在一个查询的内部还包括另一个查询,则此查询称为子查询。
Sql的任何位置都可以加入子查询。
范例:查询比7654工资高的雇员
分析:查询出7654员工的工资是多少,把它作为条件
所有的子查询必须在“()”中编写
子查询在操作中有三类:
单行单列列子查询:返回的结果是一列的一个内容
多行单列子查询:返回多个行一个列的内容,
多行子查询:返回多条记录
范例:查询出比雇员7654的工资高,同时从事和7788的工作一样的员工
范例:要求查询每个部门的最低工资和最低工资的雇员和部门名称
在返回多条记录的子查询可以把它的结果集当做一张表,给起个别名, 如图中的a。
范例:查询出来所有和每个部门最低工资的员工工资相等的人
Exists和not exists关键字的用法:
exists (sql 返回结果集为真)
not exists (sql 不返回结果集为真)
范例:查询出有员工的部门有哪些?
Union和Union All的用法
Union:对两个结果集进行并集操作,不包括重复行。
Union All:对两个结果集进行并集操作,包括重复行。