1、基本概念
oracle数据库是一个物理概念,oracle实例是数据库在内存中的镜像,属于一种逻辑概念。
oracle数据库与oracle实例至少是一对一的关系,也可能是一对多关系(oracle集群:RAC real application cluster)。
集群的优点:
- load balance 负载平衡
- fail over 失败迁移
数据文件:是一种物理概念,用来存储数据用的,后缀为.dbf的文件
表空间:表空间是一种逻辑概念,表空间有多个数据文件组成,数据文件只能属于一个表空间。
2、基本查询
命令中oracle的基本操作
- 清屏
sql
- 操作数据库
sql
tab就是当前用户的数据字典,可以查看当前用户的表和视图。
基本SQL select 语句
- 查询所有员工信息
sql
SQL优化(数据库的优化)
- 尽量使用列名,数据库在解析*号时需要耗时。
- 尽量不要使用 集合运算 符号。
- where 解析的顺序问题
- where 解析的顺序是从右往左解析;
- 所以当一个子条件为假时,and 符号左侧的条件就不再判断;
- 若Where子句和Having子句中都可以使用的条件,从语句的执行效率来看,最好写在Where子句中(where 先过滤再分组;having 先分组再过滤)
select查询语句
- 查询中的空值null问题
查询员工的年收入,其中年收入=月薪*12+奖金
select
下面的查询结果显然错误,没有奖金的员工居然没有年薪,奖金为空实际上表示奖金为零。
SQL中的null值问题:
- 空值是无效的,未指定的不可预知的值,空值并不是空格或0;
- 包含null的表达式都为null;
- null值永远!=null;
- 如果集合中含有null ,不能使用not in,但可以使用 in;
- 组函数(多行函数)自动滤空;可以嵌套滤空函数 来屏蔽他的滤空功能;
select
6. null排序 ——>降序排列时:nulls last 语句将空值显示再查询结果的最后(oracle中null值最大)
oracle中的通用函数(滤空函数):nvl(a,b) 与 nvl2(expr1,expr2,expr3)
nvl
查询奖金为null空的员工
-- 该语句无法查询出奖金为空的员工,因为null!=null
- 列的别名
- 列的别名紧跟在列名之后,也可在列名和别名之间加入关键字“AS”;
- 别名使用双引号,以便在别名中包含空格或特殊字符、数字等;
- AS 关键字可以省略;
列的别名的区别:
- 员工号与姓名这两个列名之间没有区别
- 姓名与月薪两个别名之间有区别,当别名中存在关键字、数字或者特殊符号(空格等),必须要添加双引号。
- distinct关键字——去除重复记录
-- 查询员工的部门号,不同员工属于同一部门,部门有重复
distinct 关键字 作用与select 后的所有列。distinct关键字保证所有的列组合起来是不相同的。
- 连接符
1、 把列与列,列于字符连接起来;2、用“||“表示; 3、可以用来”合成“列
--
可以使用concat()函数将两个字符串连接起来,oracle中提供dual伪表供使用
select
伪表:dual表 dual表在Oracle中是非常特殊的一张表,它存在的意义就是来满足sql99的语法格式(select后必须要有from子句存在)
字符和日期注意:
- 日期和字符只能在单引号中出现,即单引号中出现的可以是字符也可以是日期;
- 双引号中出现的是列的别名;
- 默认的日期格式:DD-Mon-RR
-- 查看日期格式
3、过滤和排序
- 比较运算符
注意:
- % 表示:任意长度的任意字符串;
- “_”表示:任意的一个字符;
- 模糊查询中,可以使用 escape 标识符 选择“%”“_”符号(即escape起到了 转义字符的功能)
-- 查询薪水在1000~2000之间的员工
- 逻辑运算符
注意:
-- 下面两条sql语句是否一样? 这两条语句完全不同,仅仅是这两条sql语句执行结果一致
- 排序
- order by 列名/表达式/别名/序号 排序方式(asc 升序 ;desc 降序)
-- 查询员工信息,按照月薪排序
2、order by 多个列的排序
-- 查询员工信息,按照月薪排序
desc 只作用于离他最近的列
select
order by 子句应当再where子句之后
参考资料:
SQL语句的语法顺序和执行顺序_tree_ifconfig的博客-CSDN博客_sql语句顺序blog.csdn.net4、单行函数
定义:操作数据对象,接受参数并返回一个结果,仅对一行进行变换,每行返回一个结果
- 字符函数
1、lower()函数、upper()函数与initcap()函数
-- 字符大小写转换
2、substr()求字串函数
-- substr(a,b) 从a串中,第b位置为开始取后面所有字符
3、instr()查找字符串函数
-- instr(a,b) 在a字符串中,查找b字符串,如果找到,返回下标,如果没找到返回0
4、length()字符数 lenghthb()字节数
sql
5、lpad()左填充 rpad()右填充
-- lpad("被填充的字串",填充几位,"用什么字符填充")
6、trim()函数
-- trim("被去除字符"from"字符串")去除前后指定的字符
7、replace()函数
-- replace('字符串','待替换字符','替换字符')替换函数
- 数字函数
1、四舍五入 round()
select
2、截断函数 trunc()
select
3、注意
round()与trunc()函数不仅仅是数字函数,也可以对日期进行操作
- 日期
oracle中的日期类型只有date类型,不同于mysql中有date与datetime两种。在oracle中date=日期+时间
-- 查询当前时间
两个日期相减返回日期之间相差的天数
-- 时间差
- 日期处理函数
- 数据转换函数
1、 隐式数据类型转换
oracle数据库自动完成数据类型间的转换
2、显示数据类型转换
-- to_char(date,'格式')
to_char()函数常用的数字格式
- 通用函数
通用函数中参数适用于任何类型数据,同时也适用于空值null
- 条件表达式
在sql中完成if-then-else的逻辑
-- 不同级别员工涨不同的钱
select
5、分组函数
分组函数作用于一组函数,并对一组数据返回一个值。
组函数(多行函数)自动滤空
- 常用的组函数
-- sum()函数 求和函数
统计函数count(*) ,统计不重复的次数时使用distinct关键字
select
- 分组数据(group by 子句)
--求每个部门的平均工资
将上面问题抽象化
select
oracle中的规定,所有包含于select列表中,而未包含于组函数中的列,都必须在group by语句中
group by 语句中出现的列,未必要在select语句中出现
select
- 多个列的分组
-- 按照不同部门的不同工种进行分组,计算工资
- 过滤分组数据 having 子句
1、行已经被分组
2、使用了组函数
3、满足having子句中条件的分组将被显示
-- 求出平均工资大于2000的部门
having 子句与where 子句的理解:
1、where后面不能使用多行函数(聚合函数,例如max、min等)
2、where 与having 的执行顺序不同:
where的搜索条件是在执行分组之前应用;
having的搜索条件是在分组条件后执行的;
如果where和having一起用时,where会先执行,having后执行;
3、Where关键字作用是过滤,选取符合条件的记录,而Having关键字作用则是为聚合结果指定条件!4、Where 子句是用来指定 "行" 的条件的,而Having 子句是指定 “组” 的条件
Where 子句 = 指定行所对应的条件
Having 子句 = 指定组所对应的条件
5、若Where子句和Having子句中都可以使用的条件,从语句的执行效率来看,最好写在Where子句中。(where 先过滤再分组;having 先分组再过滤)
where 与 having 可以通用的情况:
-- 查询10号部门的平均工资
- group by 语句 增强
-- 按照部门统计各部门不同工种的工资情况
6、多表查询
- 笛卡尔积问题
在多表连接查询问题中,连接查询会产生笛卡尔积的问题,产生很多错误的数据记录。笛卡尔积就是求出多个表的乘积,例如 emp 表与 dept 表连接,那么笛卡尔积就是 emp*dept。
上图中红框中的记录数据明显是由笛卡尔积计算而产生的错误数据。 那么多表查询产生这样的结果并不是我们想要的,那么怎么去除重复的,不想要的记录呢,当然是通过条件过滤。通常要查询的多个表之间都存在关联关系,那么就通过关联关系去除笛卡尔积。 设置表与表之间的连接条件,将多张表连接起来。
-- 连接条件
- 等值连接
通过连接条件对多张表的笛卡尔积进行过滤
--查询员工信息: 员工号 姓名 月薪 部门名称
注意:
- 在where子句中写入连接条件,
- 在表中有相同名称的列,需要在列名之前加上前缀,以区别是那一张表的列。
- 连接n张表,至少需要n-1个连接条件(例如连接3张表,就需要2个连接条件)。
- 多个连接条件需要使用 and 关键字加以合并。
- 不等值连接
连接多张表的连接条件并不是 等值 条件
--查询员工信息: 员工号 姓名 月薪 工资级别
- 外连接 ([outer] join on)
参考资料:
Oracle的连接详解(左连接、右连接、全连接...) - 无时无刻 - 博客园www.cnblogs.comOracle连接查询,彻底搞懂外连接(左外连接&右外连接)_ljinxin的博客-CSDN博客_oracle左连接查询blog.csdn.netMySQL数据库的内连接,左外连接和右外连接查询_SpiderLi的博客-CSDN博客_数据库内连接查询示例blog.csdn.netOracle中的连接查询讲解www.jianshu.com外连接结果是内连接结果的超集
在左连接和右连接时都会以一张表作为基表,该表的内容会全部的显示,然后加上两张表匹配的内容。
下面例子的SQL明显错误,由于emp表中不包含40号部门(dept表中却存在),所以在做连接查询的时候,40号部门并不能满足 “where e.deptno=d.deptno” 条件,所以等值连接查询无法查出该部门
-- 按部门统计员工人数:部门号 部门名称 人数
1、左外连接 (left [outer] join on)
- 结果包括左表(出现在JOIN子句最左边)中的所有行,不包括右表中的不匹配行
- 对于外连接,在Oracle中可以使用(+)来表示
- On子句:外连接的表之间连接条件 不使用WHERE,而是使用ON。将连接的条件放在on子句中,而且每个on子句只能指定一个连接条件。如果需要连接N个表,则需要有N-1个join-on对。
- 左连接是先查询出左表(即以左表为主),然后查询右表,右表中满足条件的显示出来,不满足条件的显示NULL。
- 希望: 对于某些不成立的记录,任然希望包含在最后的结果中 左外连接:当where e.deptno=d.deptno不成立的时候,等号左边的表任然被包含 写法:where d.deptno=e.deptno(+) 右外连接:当where e.deptno=d.deptno不成立的时候,等号右边的表任然被包含 写法: where e.deptno(+)=d.deptno
-- 按部门统计员工人数:部门号 部门名称 人数
2、 右边外连接 (right [outer] join on)结果包括右表(出现在JOIN子句最右边)中的所有行,不包括左表中的不匹配行
-- 按部门统计员工人数:部门号 部门名称 人数
3、全外连接(full [outer] join)
结果包括左、右两个表的所有行,不论他们是否匹配(即不管在另一边表中是否存在于他们匹配的行)
左外连接:返回包括左表中的所有记录和右表中联结字段相等的记录;
右外连接:返回包括右表中的所有记录和左表中联结字段相等的记录;
全外连接 :查询结果等于左外连接和右外连接的和
-- 按部门统计员工人数:部门号 部门名称 人数
- 内连接([inner] join on)
外连接结果是内连接结果的超集
内联接,结果为两个联接表中的匹配行的联接 (即 只连接两张表的匹配行)
inner join连接作为一种等值连接,其操作相当于where中的等值连接。
等值连接 的语法并不是标准的SQL99语法,属于数据库的方言, inner join 是SQL99标准的实现方式
--查询员工信息: 员工号 姓名 月薪 部门名称
- 自然连接(natural join)
连接查询会产生无用笛卡尔积,我们通常使用主外键关系等式(等值连接条件)来去除它。而自然连接无需你去给出主外键等式,它会自动找到这一等式
自然连接是在广义笛卡尔积R×S中选出同名属性上符合相等条件元组,再进行投影,去掉重复的同名属性,组成新的关系。即自然连接是在两张表中寻找那些数据类型和列名都相同的字段,然后自动地将他们连接起来,并返回所有符合条件按的结果。例emp和dept表都存在deptno列,并且类型一致,所以会被自然连接找到!
Using子句:用于显示指定两个表中的同名列,并将其作为连接条件。假设两个表中有超过一列的同名列,如果使用自然连接(natural join),则会把所有的同名列当成连接条件,使用using子句,就可以显示指定那些同名列作为连接条件。 即,using 子句可以在有多个满足条件的连接列时, 进行自主的选择
-- 按部门统计员工人数:部门号 部门名称 人数
自然连接的注意事项:
- 如果做自然连接的两个表中有多个字段都满足有相同名称和类型,那么他们都会被作为连接的条件。
- 如果自然两个表中仅字段名称相同,但是数据类型不同时,此时会返回一个错误。
- 自然连接不要用表的别名
- 自连接
通过表的别名,将同一张表视为多张表(即 自己与自己的等值连接)
-- 查询每个员工对应的老板编号(员工的上司)
自连接操作过程中会产生 笛卡尔积 ,查询结果即 表的记录的平方行记录,故自连接不适合操作大表。
- 层次查询(connect by 与 start with)
Oracle层次化查询是Oracle特有的功能实现,主要用于返回一个数据集,这个数据集存在树的关系(数据集中存在一个Pid记录着当前数据集某一条记录的Id)
层次化查询主要包含两个子句,一个start with另一个是connect by 。
start with:这个子句一般用于指定层次化查询的开始节点(也就是树的最顶级节点),找到最顶级节点,然后按照一定的规则开始查找其剩余的子节点。
connect by:这个子句就是上面所说的规则,用于查找剩余子节点的规则。
-- 查询每个员工的上司的员工编号
具有层次关系的查询,可以考虑层次查询。
根节点的定义比较灵活,但是(connect by)遍历子节点的规则,比较固定基本都是判断父节点和子节点的ID的
参考资料:
oracle 层次查询_qq_38743952的博客-CSDN博客_oracle 地区层次查询blog.csdn.net- 交叉查询(cross join)
交叉联接:结果包括两个联接表中所有可能的行组合。 即笛卡尔积连接,是两个或多个表间的无条件连接 。
交叉连接结果是其他连接结果的超集,外连接结果是内连接结果的超集
select
7、集合操作
常见的集合操作共有union与union all并集、intersect交集与minus差集。
- union与union all 并集
union与union all的作用都是合并结果集。 将是把多个select语句的查询结果合并到一起 。union与union all的区别在于:
- UNION:去除重复记录,例如:SELECT * FROM t1 UNION SELECT * FROM t2;
- UNION ALL:不去除重复记录,例如:SELECT * FROM t1 UNION ALL SELECT * FROM t2。
-- 查询10和20号部门的员工
集合运算注意点:
- 参与运算的各个集合必须列数相同且类型一致,当列数不同时,需要添加列,若类型不同时需要转换
列数不足时,补充NULL,并根据需要做相应类型转换。
-- 按照部门统计各部门不同工种的工资情况
- 采用第一个集合作为最后的表头。
- order by 永远在最后。
- 括号可以集合运算的先后顺序。
- intersect 交集
intersect 运算返回同时属于两个集合的记录(图中黄色部分)。
-- 显示薪水同时位于级别1(700~1300)和 级别2(1201~1400)的员工信息
- minus 差集
minus返回属于第一个集合,但不属于第二个集合的记录
-- 显示薪水同时位于级别1 (700~1300),但不属于级别2(1201~1400)的员工
- Mysql数据库中的集合运算
参考资料:
MySQL 并集、交集、差集_三中故人的学习笔记-CSDN博客_mysql 并集blog.csdn.netmysql数据库中只有union与union all结果集合并运算符,而没有intersect(交集)与minus(差集)运算符。但是可以通过表之间的内外连接等运算达到同样的效果。
现在有如下两张表
表object_a
表object_b
- 交集(实现intersect)
-- 使用 内连接 inner join 实现 交集运算
- 差集(实现minus)
-- 使用 左外连接 实现差集运算 (获取a - b 表)
- 补集
-- 使用 左外连接 实现补集运算
8、子查询
To be continued......