alin的学习之路(数据库篇:三)(多表查询,子查询,集合运算,数据处理)

1. 多表查询

1.1 笛卡儿积

笛卡尔积就是两个集合的乘积计算 。
如果多个表进行联合查询, 得到结果是一个笛卡尔积, 举例: 比如有两个表 aaa , bbb
行数: 两个表中行数的乘积
列数: 两个表中列数之和

1.2 等值连接/不等值连接

等值连接和不等值连接的作用: 通过判断过滤多表查询得到的笛卡尔积中的无效数据

等值连接和不等值连接的区别:where后面判断条件使用的符号是 = 还是其他符号

  • 等值连接

查询员工信息:员工号,姓名,月薪(在emp表中)和部门名称(在dept表中)

-- from后边可以加多张表, 表名之间使用 ,(逗号) 间隔
-- select 后边的列名, 一般不是直接指定, 而是: 表名.列名SQL> select e.empno, e.ename, e.sal, d.dname from emp e, dept d where e.deptno=d.deptno;EMPNO ENAME                                                    SAL DNAME
----- -------------------------------------------------- --------- ------------------------------7840 岸本_齐史                                            5000.00 周刊少年Jump7839 尾田_荣一郎                                          5000.00 周刊少年Jump7521 娜美                                                 4560.00 草帽海贼团7566 蒙奇·D·路飞                                         5450.00 草帽海贼团7654 妮可·罗宾                                           5500.00 草帽海贼团7788 乌索普                                               3000.00 草帽海贼团7708 Brook                                                3000.00 草帽海贼团-- 其中emp后面的e,以及dept后面的d,表示表的别名。可以用来修饰列名。-- 也可以不用别名直接用表名,会显得冗杂
  • 不等值连接
  1. 询员工信息:员工号, 姓名, 月薪 和 月薪级别(salgrade表)
-- 员工号,姓名,月薪在 emp 表中
-- 月薪级别在 salgrade 表中SQL> select e.empno, e.ename, e.sal from emp e, salgrade s where e.sal between s.losal and s.hisal ;EMPNO ENAME                                                    SAL
----- -------------------------------------------------- ---------7934 托尼托尼·乔巴                                         800.687876 布鲁克                                               1100.007844 弗兰奇                                               1500.007707 Franky                                               2000.007900 甚平                                                 2000.007701 Roronoa Zoro                                         2000.007699 夏奇                                                 2050.007782 贝波                                                 2450.007703 Usopp                                                2500.00
  1. 按部门统计员工人数,显示如下信息:部门号,部门名称,人数
-- 部门号和部门名称在dept表中
-- 人数的统计需要在 emp 表中完成SQL> select d.deptno, d.dname ,count(e.ename) from dept d, emp e where d.deptno=e.deptno
group by d.deptno, d.dname ;DEPTNO DNAME                          COUNT(E.ENAME)
------ ------------------------------ --------------10 周刊少年Jump                                240 红发海贼团                                  560 D之一族                                     850 黑胡子海贼团                                 420 草帽海贼团                                 1930 红心海贼团                                  76 rows selected

上述结果中是没有将 45 号部门统计到查询的结果集中的, 应该如何也将其统计到结果集中?

因为45号部门在emp表中没有该部门的成员,所以45号部门并未统计进入该查询。如果想要显示45号部门,需要使用外连接。

1.3 外连接

使用select, 在最后的查询结果中,如果想要包含某些对于where条件来说不成立的记录 , 我们可以使用外
连接. 外连接分为 左外连接 和 右外连接 .
在左连接和右连接时都会以一张A表为基础表,该表的内容会全部显示,然后加上A表和B表匹配的内
容。 如果A表的数据在B表中没有记录。 那么在相关联的结果集行中列显示为空值(NULL)。
对于外连接, 可以使用“(+) ”来表示。 关于使用(+)的一些注意事项:

  1. (+)操作符只能出现在WHERE子句中。
  2. 当使用(+)操作符执行外连接时,如果在WHERE子句中包含有多个条件,则必须在所有条件
    中都包含(+)操作符。
  3. (+)操作符只适用于列,而不能用在表达式上。
  4. (+)操作符不能与 OR 和 IN 操作符一起使用。
  5. (+)操作符只能用于实现左外连接和右外连接,而不能用于实现完全外连接。
    通过 (+) 就可以对查询的结果进行补充, 补充不满足条件的那一方
    举例: where e.deptno = d.deptno
    在d表中 有45 这个部门, 也就是 d.deptno 有可能 等于45
    在表 e中没有45号部门的员工, 因此 e.deptno 绝对不会等于45
    使用 (+) 就可以对不满足条件的结果进行补充, 根据上述的描述 e.deptno 是需要补充的,
    因此将 (+) 写到 e.deptno 后边就可以
    where e.deptno(+) = d.deptno , 要补充的是数据来自于等号右侧的 d.deptno
    这样当 d.deptno=45 的时候 where e.deptno = d.deptno 这个条件成立
  • 左外连接(左边的表不加限制)

用(+)来实现, 这个+号可以这样来理解: + 表示补充,即哪个表有加号,这个表就是匹配
表。如果加号写在右表,左表就是全部显示,所以是左连接。

通俗理解:哪个表少数据了,就在哪个表的那一端加上(+)

-- 再回到刚才的问题,如果想要在查询中也显示出45号部门的员工人数,则需要使用外连接SQL> select d.deptno, d.dname ,count(e.ename) from dept d, emp e where d.deptno=e.deptno(+) group by d.deptno, d.dname ;DEPTNO DNAME                          COUNT(E.ENAME)
------ ------------------------------ --------------10 周刊少年Jump                                240 红发海贼团                                  545 黑桃海贼团                                  060 D之一族                                     850 黑胡子海贼团                                 420 草帽海贼团                                 1930 红心海贼团                                  77 rows selected
  • 右外连接(右边的表不加限制)
用(+)来实现, 这个+号可以这样来理解: + 表示补充,即哪个表有加号,这个表就是匹配
表。如果加号写在左表,右表就是全部显示,所以是右连接。SQL> select d.deptno, d.dname ,count(e.ename) from dept d, emp e where e.deptno(+)=d.deptno group by d.deptno, d.dname ;DEPTNO DNAME                          COUNT(E.ENAME)
------ ------------------------------ --------------10 周刊少年Jump                                240 红发海贼团                                  545 黑桃海贼团                                  060 D之一族                                     850 黑胡子海贼团                                 420 草帽海贼团                                 1930 红心海贼团                                  77 rows selected-- 以上结果和左外连接相同,只是sql语句的书写方式不同

1.4 自连接

自连接: 通过给当前表设置不同的别名,将同一张表视为多张表来使用, 进行多表联查。(也就是自己和自己对比)

举例: 查询 xxx员工的老板是 yyy, 最后将尾田/岸本的老板也显示出来

-- emp 表中有一个字段叫做 mgr ,存放的是员工的老板数据,只要取出mgr中的数据对应到emp表中查询即可完成查询SQL> select e.ename "员工", b.ename "老板" from emp e, emp b where e.mgr=b.empno;
-- 使用这一条语句可以发现结果中少了两个记录,因为尾田/岸本在表中没有老板,所以没有显示,这个时候要加上自连接SQL> select e.ename "员工", b.ename "老板" from emp e, emp b where e.mgr=b.empno(+);
-- 自连接的理念和外连接一样,哪端的数据少就在哪端加(+),b表中缺少数据,所以在b表一端加上(+)
员工                                               老板
-------------------------------------------------- --------------------------------------------------
阿巴罗·皮萨罗                                      马歇尔·D·帝奇
芝沙斯·巴沙斯                                      马歇尔·D·帝奇
岸本_齐史
尾田_荣一郎                                        45 rows selected-- 如果要想给尾田/岸本在查询后增加个显示,需要再搭配nvl使用
SQL> select e.ename "员工", nvl(b.ename,'他老婆') "老板" from emp e, emp b where e.mgr=b.empno(+);
员工                                               老板
-------------------------------------------------- --------------------------------------------------
阿巴罗·皮萨罗                                      马歇尔·D·帝奇
芝沙斯·巴沙斯                                      马歇尔·D·帝奇
岸本_齐史                                          他老婆
尾田_荣一郎                                        他老婆45 rows selected

2. 子查询

子查询就是select 语句的嵌套使用, 即: 在select中使用select。 表示子语句的select需要写在()中
写到()中的select执行的优先级高

2.1 同表子查询

举例: 查询比 路飞 工资高的员工信息

-- 先查出路飞的工资是多少
SQL> select sal from emp where ename like '%路飞%';SAL
---------5450.00-- 然后再和路飞的工资比较得出查询
SQL> select ename, sal from emp where sal>(select sal from emp where ename like '%路飞%');ENAME                                                    SAL
-------------------------------------------------- ---------
妮可·罗宾                                           5500.00
特拉法尔加·D·瓦铁尔·罗                             5655.00
香克斯                                               6000.00
本·贝克曼                                           5500.00
耶稣布                                               5500.00
马歇尔·D·帝奇                                       5675.00
Monkey·D·Luffy                                     5500.00
Trafalgar·D·Water·Law                             5800.00
Marshall·D·Teach                                   7800.00
Portgas·D·Ace                                      5500.00
Gol·D·Roger                                        7500.00
Monkey·D·Dragon                                    6550.00
Monkey·D·Garp                                      7890.0013 rows selected

2.2 不同表子查询

举例: 查询部门名称是 草帽海贼团 的员工信息

-- 先查询部门名称是 草帽海贼团 的部门编号
SQL> select deptno from dept where dname='草帽海贼团';DEPTNO
------20-- 通过部门编号过滤得到 草帽海贼团 的员工信息
SQL> select * from emp where deptno=(select deptno from dept where dname='草帽海贼团');

2.3 在select、from、where、having后边使用子查询

  • 在select后使用子查询 - 不常用

查询20号部门的员工号、员工姓名、部门编号、部门名称

-- 员工信息: emp表, 可以得到 员工号、员工姓名、部门编号, 部门名称在dept表
select empno, ename, deptno, (select dname from dept where deptno = 20)from emp
where deptno = 20;
  • 在from后使用子查询 – 更不常用

在使用select进行查询的时候, from关键字值可以 指定表名 或者 一个结果集 即查询的结果. 子
查询的结果就是一个结果集, 因此可以将子查询直接写到from的后边.

-- 举例
select ename, sal from (select ename, sal, sal*12 from emp);
  • where后使用子查询 --> 常用的方式

查询比平均工资高的员工信息

-- 首先查询出平均工资
SQL> select avg(sal) from emp;AVG(SAL)
----------
3932.03733-- 然后用在emp表中判断工资是否大于平均工资
SQL> select ename, sal from emp where sal>(select avg(sal) from emp);ENAME                                                    SAL
-------------------------------------------------- ---------
娜美                                                 4560.00
蒙奇·D·路飞                                         5450.00
妮可·罗宾                                           5500.00
  • 在having后使用子查询

分组统计需要使用关键字: group by , 在这个关键字后边进行数据过滤需要使用关键字 having

查询部门的平均薪资, 并且该部门的平均薪资高于30号部门的平均薪资

-- 首先求出30号部门的平均薪资
SQL> select avg(sal) from emp where deptno=30;AVG(SAL)
----------
3322.14285-- 再分组统计每个部门的平均薪资与30号部门的平均薪资比较
SQL> select deptno, avg(sal) from emp group by deptno having avg(sal)>(select avg(sal) from emp where deptno=30);DEPTNO   AVG(SAL)
------ ----------40       464050     3996.510       500060    6248.75-- 如果再增加需求:在结果集中, 显示部门名称和部门ID
-- 需要使用多表查询,因为部门名称在dept表中
SQL> select d.deptno, d.dname, avg(e.sal)from emp e, dept dwhere d.deptno = e.deptnogroup by d.deptno, d.dname
having avg(e.sal) > (select avg(sal) from emp where deptno = 30);DEPTNO DNAME                          AVG(E.SAL)
------ ------------------------------ ----------10 周刊少年Jump                         500040 红发海贼团                           464060 D之一族                           6248.7550 黑胡子海贼团                        3996.5

查询部门的最低月薪并且该部门最低月薪高于50号部门的最低月薪

-- 首先查询50号部门的最低月薪,再用于月薪的比较判断
SQL> select d.deptno, d.dname, min(e.sal)from emp e, dept dwhere d.deptno = e.deptnogroup by d.deptno, d.dname
having min(sal) > (select min(sal) from emp where deptno = 50);DEPTNO DNAME                          MIN(E.SAL)
------ ------------------------------ ----------10 周刊少年Jump                         500040 红发海贼团                           260060 D之一族                              3450

2.4 单行/多行子查询

  • 单行子查询

单行子查询就是 该条子查询执行结束时,只返回一条记录(一行数据)。
在当行子查询中只能使用单行操作符: 使用单行操作符: = 、 > 、 >= 、 < 、 <= 、 <>

上面的例子全是单行子查询

举例: 查询工资比 路飞 工资高的员工的信息

-- 先查出路飞的工资是多少
SQL> select sal from emp where ename like '%路飞%';SAL
---------5450.00-- 然后再和路飞的工资比较得出查询
SQL> select ename, sal from emp where sal>(select sal from emp where ename like '%路飞%');
  • 多行子查询

多行子查询就是 该条子查询执行结束时,只返回多条记录(多行数据)。
多行操作符有:

  • IN: 等于列表中的 任意 一个
  • ANY: 和子查询返回的 某一个 值比较
  • ALL: 和子查询返回的 所有 值比较

与每个比较运算符一起使用时的含义:

条件 表示含义
c = ANY (…) c列中的值必须与集合中的一个或多个值匹配,以评估为true
c != ANY (…) c列中的值不能与集合中的一个或多个值匹配以评估为true
c > ANY (…) c列中的值必须大于要评估为true的集合中的最小值。
c < ANY (…) c列中的值必须小于要评估为true的集合中的最大值。
c>= ANY (…) c列中的值必须大于或等于要评估为true的集合中的最小值。
c <= ANY (…) c列中的值必须小于或等于要评估为true的集合中的最大值。

下表说明了SQL ALL运算符的含义:

条件 描述
c > ALL(…) c列中的值必须大于要评估为true的集合中的最大值。
c >= ALL(…) c列中的值必须大于或等于要评估为true的集合中的最大值。
c < ALL(…) c列中的值必须小于要评估为true的集合中的最小值。
c <= ALL(…) c列中的值必须小于或等于要评估为true的集合中的最小值。
c <> ALL(…) c列中的值不得等于要评估为true的集合中的任何值。
c = ALL(…) c列中的值必须等于要评估为true的集合中的任何值。
  1. 查询部门名称为 红心海贼团 和 红发海贼团 的员工信息
-- 先查询出部门名称为 红心海贼团 和 红发海贼团 的部门编号,是一个集合
SQL> select deptno from dept where dname in ('红心海贼团', '红发海贼团');DEPTNO
------3040-- 再根据这个部门编号集合查询对应的员工信息
SQL> select * from emp where deptno in (select deptno from dept where dname in ('红心海贼团', '红发海贼团'));
  1. 查询所有月薪比30号部门薪资最低者的工资高的员工信息
------------------ 单行子查询处理思路 ------------------
-- 查询出30号部门工资最低者的工资
SQL> select min(sal) from emp where deptno=30;MIN(SAL)
----------2050
-- 再通过这个最低工资来进行过滤
SQL> select * from emp where sal>(select min(sal) from emp where deptno=30);------------------ 单行子查询处理思路 ------------------
-- 查出30号部门的所有人的工资,组成一个集合
select sal from emp where deptno=30;
-- 通过这个集合来进行过滤,可以使用 any 关键字
SQL> select * from emp where sal>any(select sal from emp where deptno=30);注意:>any() 表示大于any中的最小值即为true
  1. 查询比30号部门所有员工工资都高的员工信息
------------------ 单行子查询处理思路 ------------------
-- 查询出30号部门工资最高者的工资
SQL> select max(sal) from emp where deptno=30;-- 再通过这个最低工资来进行过滤
SQL> select * from emp where sal>(select max(sal) from emp where deptno=30);------------------ 单行子查询处理思路 ------------------
-- 查出30号部门的所有人的工资,组成一个集合
select sal from emp where deptno=30;
-- 通过这个集合来进行过滤,可以使用 any 关键字
SQL> select * from emp where sal>all(select sal from emp where deptno=30);注意:>all() 表示大于any中的最大值即为true

2.5 子查询中的NULL

判断一个值等于、不等于空,不能使用=和!=号,而应该使用is 和 not。

如果集合中有NULL值, 不能使用not in。例如:not in (10, 20, NULL),但是可以使用 in

查询不是管理者的员工信息。

-- 查询的表是员工信息表-> emp
-- 如何确定员工是是不是管理者: 在数据库表的 mgr 字段的值对应的是员工的编号, 只要员工编号出现在这一列, 这个员工就是一个管理者-- 查询是管理者的员工的信息
-- 这个查询对应的结果集中有空字段null,注意使用distinct关键字,因为不同员工有相同的管理者
SQL> select distinct mgr from emp;MGR
-----783976987902756661006 rows selected-- 上面的结果显示有6条查询,但只有5条显示,因为结果集中有null字段。
-- 所以注意要将mgr是空的条目过滤掉,使用is not null
SQL> select * from emp where empno not in(select distinct mgr from emp where mgr is not null);

3. 集合运算

3.1 交集、并集、差集

关键字: 并集: union, 全并集: union all, 交集: intersect, 差集: minus

比如说有集合 A ( 1 , 2 , 3 ) , B ( 2 , 3 , 4 ):

  • A∪B(取并集) = ( 1, 2, 3, 4) ,如果是全并集就是 (1, 2, 3, 2, 3, 4)

  • A∩B (取交集) = ( 2, 3 )

  • A – B(取差集) = ( 1 ) ,B – A = (4)

-- 并集
select * from emp where deptno=10 union
select * from emp where deptno=20;-- 全并集
select * from emp where deptno=10 union all
select * from emp where deptno in(10,20);-- 交集
select * from emp where deptno=10 intersect
select * from emp where deptno in(10,20);-- 差集, 剩下30号部门信息
select * from emp where deptno in(10, 30) minus
select * from emp where deptno in(10,20);-- 交换位置, 剩下20号部门信息
select * from emp where deptno in(10, 20) minus
select * from emp where deptno in(10,30);

3.2 集合使用的注意事项

  1. 参与运算的各个集合必须列数相同,且类型一致

    -- 错误的例子
    -- 两个集合列数不一致,
    select ename, deptno from emp where deptno=10 union
    select * from emp where deptno=20;-- 查询的数据类型不一致
    select ename, deptno from emp where deptno=10 union
    select deptno, ename from emp where deptno=20;
    
  2. 采用第一个集合的表头作为最终使用的表头。

    select ename "员工信息", deptno "部门ID" from emp where deptno=10 union
    select ename "Name", deptno "ID" from emp where deptno=20;
    
  3. 可以使用括号()先执行后面的语句。

    select ename "员工信息", deptno "部门ID" from emp where deptno=10 union
    

(select ename “Name”, deptno “ID” from emp where deptno=20);

# 4. 数据处理## 4.1 插入数据```sql
-- 语法格式:
insert into 表名[列名1,列名2,...] values(列值1,列值2,...);
SQL> desc bonus;
Name  Type         Nullable Default Comments
----- ------------ -------- ------- --------
ENAME VARCHAR2(10) Y
JOB   VARCHAR2(9)  Y
SAL   NUMBER       Y
COMM  NUMBER       Y

上述是一张空表,可以用来测试数据处理。

  • 插入全部列
-- 给所有的列指定出数据值,这时表名后面的列名可以不写
SQL> insert into bonus values('lily','后台',10000,10000);SQL> select * from bonus;ENAME      JOB              SAL       COMM
---------- --------- ---------- ----------
lily       后台           10000      10000
  • 插入部分列/隐式插入null
-- 在插入数据的时候可指定部分列的值, 没有指定值的字段就是空字段
-- 如果指定部分列的值, 需要将列名一并写出,写在表名后面
SQL> insert into bonus(ename, sal, comm) values('tom', 20000, 10000);1 row insertedSQL> select * from bonus;ENAME      JOB              SAL       COMM
---------- --------- ---------- ----------
lily       后台           10000      10000
tom                       20000      10000
  • 显示插入null
-- 可以显示的指定某一个字段值为空
SQL> insert into bonus values('tom', null, 20000, 10000);1 row insertedSQL> select * from bonus;ENAME      JOB              SAL       COMM
---------- --------- ---------- ----------
lily       后台           10000      10000
tom                       20000      10000
tom                       20000      10000

4.2 更新数据

-- 语法结构:
update 表名 set 列名1=列值[,列名2=列值,...] where 列名=列值(条件);
SQL> select * from bonus;ENAME      JOB              SAL       COMM
---------- --------- ---------- ----------
lily       后台           10000      10000
tom                       20000      10000
tom                       20000      10000SQL> update bonus set sal=25000 where ename='tom';2 rows updatedSQL> select * from bonus;ENAME      JOB              SAL       COMM
---------- --------- ---------- ----------
lily       后台           10000      10000
tom                       25000      10000
tom                       25000      10000

4.3 删除数据

-- 语法格式:
delete from 表名;     -- 表示删除表中的全部数据delete from 表名 where 列名=列值(条件);   -- 表示按条件筛选删除-- 举个栗子
SQL> delete from bonus where ename='lily';1 row deletedSQL> select * from bonus;ENAME      JOB              SAL       COMM
---------- --------- ---------- ----------
tom                       25000      10000
tom                       25000      10000SQL> delete from bonus;2 rows deletedSQL> select * from bonus;ENAME      JOB              SAL       COMM
---------- --------- ---------- ----------

4.4 事务

4.4.1 什么是数据库事务

数据库事务是构成单一逻辑工作单元的操作集合

  • 多个操作的集合, 这些操作中必须要涉及到数据库数据的写操作
  • 如果都是读操作, 根本不需要事务

比如: 转账是生活中常见的操作,比如从A账户转账100元到B账号。站在用户角度而言,这是一个逻辑上的单一操作,然而在数据库系统中,至少会分成两个步骤来完成:

  1. 将A账户的金额减少100元

  2. 将B账户的金额增加100元。

在这个过程中可能会出现以下问题:

  1. 转账操作的第一步执行成功, A账户上的钱减少了100元, 但是第二步执行失败或者未执行便发生系统崩溃,导致B账户并没有相应增加100元。
  2. 转账操作刚完成就发生系统崩溃,系统重启恢复时丢失了崩溃前的转账记录。
  3. 同时又另一个用户转账给B账户,由于同时对B账户进行操作,导致B账户金额出现异常。
  4. 这个交易的过程不能出现任何异常
    • 如果出现了异常, 需要进行状态的回滚, 回滚到交易开始的时候 == > 复原
    • 如何有事务就可以还原状态, 如果没有事务就无法还原
  5. 事务的作用:
    • 在交易开始的时候开启一事务, 记录当前的状态
    • 交易过程中判断每一步是否成功了, 成功: 继续, 失败: 不继续交易, 状态回滚到开始的时候

为了便于解决这些问题,需要引入数据库事务的概念。

关于事务有以下几点特性:

  1. 数据库事务可以包含一个或多个数据库操作, 但这些操作构成一个逻辑上的整体,构成逻辑整体的这些数据库操作, 要么全部执行成功, 要么全部不执行。 – 原子性
  2. 构成事务的所有操作, 要么全都对数据库产生影响, 要么全都不产生影响, 即不管事务是否执行成功, 数据库总能保持一致性状态。 – 一致性
  3. 事务的执行不受其他事务的干扰,当数据库被多个客户端并发访问时,会隔离它们的操作,防止出现:脏读、幻读、不可重复读 。 – 隔离性
  • 脏读是指一个事务读取了另一个事务未提交的数据
  • 不可重复读是指一个事务对同一数据的读取结果前后不一致。
  • 幻读是指事务读取某个范围的数据时,因为其他事务的操作导致前后两次读取的结果不一致。
  • 幻读和不可重复读的区别在于,不可重复读是针对确定的某一行数据而言, 而幻读是针对不确定的多行数据。
  1. 对于任意已提交事务,系统必须保证该事务对数据库的改变不被丢失,即使数据库出现故障。–持久性

4.4.2 oracle中的事务

  • 设置保存点

    -- 在写数据库之前, 需要设置保存点 ===> 开启了一个事务
    -- 保存点的名字不允许重名
    sql> savepoint 保存点的名字;
    
  • 回滚到保存点

    -- 事务对应的操作集合有一步失败了, 需要进行数据的回滚
    -- 回滚就是内存数据的覆盖, 用旧的数据覆盖新的数据
    

sql> rollback to savepoint 保存点的名字;


- 提交事务```sql
-- 提交之后保存点就不存在了, 提交之后不能回滚
-- 提交就是将内存数据写入到磁盘的数据库文件中
sql> commit;
  • 举例

    -- 一个完整的操作(一个事务), 这个操作需要若干步来完成
    -- 设置一个保存点 a
    -- 状态: 空表
    SQL> savepoint a;Savepoint created-- 插入数据
    SQL> insert into bonus values('tom', '董事长', 10000, 2000);1 row insertedSQL> insert into bonus values('jack', '销售', 1000, 2000);1 row inserted-- 添加保存点 b
    -- 状态: 数据库表中 有两条记录
    SQL> savepoint b;Savepoint createdSQL> insert into bonus values('lucy', '秘书', 10000, 20000);1 row insertedSQL> insert into bonus values('lily', '小秘书', 9000, 20000);1 row inserted-- 添加保存点c
    -- 数据库表中有4条数据
    SQL> savepoint c;Savepoint createdSQL> delete from bonus where ename = 'lily';1 row deletedSQL> select * from bonus;ENAME      JOB              SAL       COMM
    ---------- --------- ---------- ----------
    tom        董事长         10000       2000
    jack       销售            1000       2000
    lucy       秘书           10000      20000-- 回滚到保存点c
    -- 重新回到有4条记录的表状态
    SQL> rollback to savepoint c;Rollback completeSQL> select * from bonus;ENAME      JOB              SAL       COMM
    ---------- --------- ---------- ----------
    tom        董事长         10000       2000
    jack       销售            1000       2000
    lucy       秘书           10000      20000
    lily       小秘书          9000      20000-- 当确定所有的数据库操作都没有问题, 提交事务
    SQL> commit;Commit complete
    

alin的学习之路(数据库篇:三)(多表查询,子查询,集合运算,数据处理)相关推荐

  1. JAVA学习之路--基础篇三

    目录 关于Java中从键盘输入的语句 nextxxx().next().nextLine()的区别 语句 if和if else语句 Switch语句 for语句 while和do..while bre ...

  2. alin的学习之路(数据库篇:二)(select查询,where条件查询,order by排序,单行函数,多行函数,group by分组)

    alin的学习之路(数据库篇:二)(select查询,where条件查询,order by排序,单行函数,多行函数,group by分组) 1. SQL语句 1.1 sql语言类型 sql是一门独立的 ...

  3. alin的学习之路(数据库篇:五)(MySQL的相关语句及API的C语言实现)

    alin的学习之路(数据库篇:五)(MySQL的相关语句及API的C语言实现) 1. MySQL概述与登陆MySQL mysql 与 oracle 的区别 oracle 是一个数据库实例下有多个用户, ...

  4. alin的学习之路:面试题 数据库相关

    alin的学习之路:面试题 数据库相关 如何提高查询速度? 使用索引 create index 索引名 on 表名(列名1,列名2,--); 数据库索引,事务,事务级别 使用索引可以提高查询效率 事务 ...

  5. alin的学习之路:在Qt中使用Oracle数据库

    alin的学习之路:在Qt中使用Oracle数据库 1. 准备工作 在Qt中安装好Source插件,将其中的oci模块进行编译,注意要在oci.pro中指定数据块的动态库和头文件路径 需要在Qt项目文 ...

  6. alin的学习之路(Linux系统编程:三)(vim,gcc,库,gdb)

    alin的学习之路(Linux系统编程:三)(vim,gcc,库,gdb) 1.vim的使用 vim有三种模式:命令模式,末行模式,编辑模式 光标的移动[命令模式] h 向左 ,j 向下,k 向上,l ...

  7. 大数据学习之路 JUC篇

    大数据学习之路 JUC篇(1) 前提说明 本人是一名学生,茫茫it行业的一名卑微的小白,这是我第一次写博客.其原因是学着学着知识发现回顾的时候差不多全忘记了!!为了总结.复习自己以往学到过的有关大数据 ...

  8. alin的学习之路:加密相关知识(加密和解密,常见加密算法,消息验证码HMAC,数字签名)

    alin的学习之路:加密相关知识(加密和解密,常见加密算法,消息验证码HMAC,数字签名) 1. 加密和解密 1.1 加密的三要素 原始数据 加密操作: 明文 -> 密文 解密操作: 密文 -& ...

  9. alin的学习之路:面试题 计算机网络相关

    alin的学习之路:面试题 计算机网络相关 介绍下proactor和reactor reactor:同步IO proactor:异步IO Reactor框架中用户定义的操作是在实际操作之前调用的.比如 ...

最新文章

  1. 多线程处理缓慢_华为昇腾,AI推理性能超越对手一倍:软件挖掘处理器全部潜力...
  2. 禁止Win7系统自动安装驱动程序
  3. 这引人联想的机械右手!玩转魔方,灵活不输人类,OpenAI:前所未有
  4. 光在介质中传播速度—材料折射率变化—物理光学记录
  5. 生命的力量:萝卜开花
  6. 数据库实例:mysql与mongo结合用户登录
  7. 团队项目讨论及计划修订版
  8. Java虚拟机------JVM分析工具
  9. nginx源码分析(2)——http模块的初始化过程
  10. [转]Python中下划线---完全解读
  11. 控制led闪烁次数_单片机驱动LED灯的进阶之路
  12. 从0到1实现VueUI库思路
  13. Apache Commons BeanUtils包学习 2 -beanutils PropertyUtils bean
  14. SDU创新实训 6.实现中文拼音模糊匹配
  15. 了解Minimax算法
  16. 随机森林——股票涨跌预测模型搭建
  17. 信息收集(一)之whois查询
  18. TypeScript-基础类型学习
  19. Python语法易混淆
  20. 云服务器和虚拟主机有什么区别?哪个比较好呢?

热门文章

  1. 成都市武侯区计算机实验学校,成都市武侯区金辉实验学校
  2. MeeGo编译步骤参考
  3. echarts社区热词图、echart金字塔图
  4. php 数组分割,php 数组分割的方法
  5. 苏州印象--2006
  6. MySQL闪回-binlog2sql
  7. 超级表格:要山寨Excel,还是与之Say Byebye?
  8. 反渗透设备:反渗透设备工艺先进
  9. DS18B20 FPGA
  10. printf打印问题