数据结构
概念:RDBMS:relational database manager system
mysql:
-- 数据库系统
---- 多个数据库database
------ 多个表table
oracle:
-- oracle系统
---- 多个服务service(oracle实例):ORCL
------ 多个用户user
-------- 多个表table
---------- 表空间tablespce:数据的物理存储(硬盘中文件)
表空间:一个用户可以制定多个表空间,一个表空间可以存储多个表的数据
位置:E:\oracle
xxx.DBF::::存储表空间数据的文件
xxx.LOG::::日志文件
xxx.CTL::::记录权限文件
sql
概念:structured query language 结构化查询语言: 针对于关系型数据库的统一的操作语言
按功能分类:
1 ddl: data defined language:数据定义:
对表结构的增删改查:create、drop、alter
2 dml: data manipulation language:数据操纵
对表记录的增删改:insert、delete、update
3 dql: data query language:数据查询
对表记录的查询:select
4 dcl: data controllanguage:权限控制
对用户权限的控制:grant、revoke
5 tcl: transaction control language:事务管理
对事务操纵:rollback、commit -> 描述同一个业务的多个dml语句,要么都成功,要么都失败
ddl:表结构增删改查
/*** 关于用户的ddl ***/
-- 创建用户时必须指定其存储数据的表空间
create tablespace wen_1 datafile 'E:\oracle\wen_1.DBF'size 10M;
-- 创建用户
create user wen identified by "123456" default tablespace wen_1;
-- 授予其登录权限
grant create session to wen;
-- 授予其创建表的权限
grant create table to wen;
-- 授予其DBA角色(权限的集合)
grant dba to wen;
-- 撤销其DBA角色
revoke dba from wen;
-- 撤销其创建表的权限
revoke create table from wen;
-- 删除用户
drop user wen cascade;
-- 显示当前用户
select * from user_users;
-- 修改用户密码
alter user wen identified by "123";
==================================================
/*** 创建表的ddl ***/
-- 查询当前用户下的所有表
select * from tabs;
drop table tab_1;
create table tab_1(
tid int primary key,
tname varchar(10),
tsex char(1),
tbirthday date,
tsalary decimal(4,1),
tscore1 float,
tscore2 number(4,1)
);
==================================================
/*** 约束 ***/
1 非空约束:not null
2 唯一约束:unique
3 默认约束:default
4 检查约束:check
create table tab_4(
tsex char(3),
check (tsex = '男' or tsex ='女')
);
create table tab_4(
tsex char(3) check (tsex = '男' or tsex ='女')
);
insert into tab_4 values('男');
insert into tab_4 values('妖');
5 主键约束: primary key
特点: 1 唯一 2 非空 3 可以被引用
6 外键约束: foreign key
特点: 1 可以重复 2 可以为空 3 如果有值,此值在主表的主键列必须存在
==================================================
/*** 对表结构进行增删改查的ddl ***/
drop table tab_5;
create table tab_5(
tid int primary key,
tname varchar(20),
tsex char(3),
tsage int
);
-- oracle不识别desc查询表结构
desc tab_5;
-- 查询表结构
select * from user_tab_columns where Table_Name='TAB_55';
-- 查看表约束
select * from user_constraints where Table_Name='TAB_55';
-- 修改表名
alter table tab_5 rename to tab_55;
-- 添加列
alter table tab_55 add tdy int;
-- 删除列
alter table tab_55 drop column tdy;
-- 修改列名
alter table tab_55 rename column tsage to tage;
-- 修改列类型
alter table tab_55 modify tage integer;
==================================================
/*** 关于主键约束的ddl ***/
-- 1:创建表时定义主键约束
create table tab_6(
tid int primary key,--创建表时定义主键约束
tname varchar(100)
);
create table tab_6(
tid int,
tname varchar(100),
primary key(tid)--创建表时定义主键约束
);
-- 2:删除主键约束
alter table tab_6 drop primary key;
-- 3:创建表后 添加主键约束
alter table tab_6 add primary key(tid);
alter table tab_6 modify tid int primary key;
-- 查询所有的列结构
select * from user_tab_columns where Table_Name='TAB_6';
-- 查询所有的约束
select * from user_constraints where Table_Name='TAB_6';
==================================================
/*** 关于外键约束的ddl ***/
-- 1:创建表时定义外键约束
create table tab_6(
tid int,
tids int,
constraint fk_1 foreign key(tids) references tab_55(tid)--定义外键约束
);
create table tab_6(
tid int,
tids int references tab_55(tid)--定义外键约束
);
-- 2:删除外键约束
alter table tab_6 drop constraint fk_1;
alter table tab_6 drop constraint SYS_C0011116;
-- 3: 创建表后 添加外键约束
alter table tab_6 add constraint fk_2 foreign key(tids) references tab_55(tid);
alter table tab_6 add foreign key(tids) references tab_55(tid);
-- 查询所有的列结构
select * from user_tab_columns where Table_Name='TAB_6';
-- 查询所有的约束
select * from user_constraints where Table_Name='TAB_6';
==================================================
/**
注意1:oracle中字符串写在单引号中
注意2:oracle中不支持boolean
注意3:oracle中float不能加精度
注意4:oracle中没有double类型,可以通过number(n,m)来表示double
注意5:oracle中char(n)/varchar(n) n是字节个数
mysql中char(n)/varchar(n) n是字符个数
注意6:dual表是万能表: 满足oracle对select必须有from要求
注意7:oracle中事务(dml语句)默认是手动提交的
**/
==================================================
/**
oracle中的数据类型:
整数类型:
int
integer
number(10,0)
浮点类型:
float
number(n,m)
decimal(n,m)
字符类型:
varchar(n):可变长度 :n最大值4000
char(n):固定长度 :n最大值2000
varchar2(n):可变长度 :n最大值4000
clob :4G
字节类型:
blob :4G
日期类型:
date: 精确到秒
timestamp: 精确到微秒
布尔类型:
不支持
**/
dml:表记录增删改
*** 对表记录的增删改: delete、insert、update ***
注意1:oracle不支持insert一条语句插入多条记录
注意2:drop、delete、truncate的区别
drop table tab_3;
create table tab_3(
tid int,
tname varchar(100)
);
insert into tab_3 values(1,'a');
insert into tab_3 values(2,'b');
insert into tab_3 values(3,'c');
drop table tab_3;
delete from tab_3;
truncate table tab_3;
select * from tab_3;
alter table tab_3 add tsex char(3) default '女';
update tab_3 set tsex='男' where mod(tid,3)=1;
update tab_3 set tsex='仙' where mod(tid,3)=2;
dql:表记录查询
数据查询: select
select单表查询:
1: 查询所有列->select * from tab_3
2: 查询指定列->select 列名1,列名2 from 表名;
3: 查询指定列不为null记录数->select count(列名) from 表名
查询总记录数->select count(*) from 表名
4: 起别名as->select tname 名字, tid as "编号" from tab_3;
5: 去除重复记录:distinct
select distinct tname 名字, tid as "编号" from tab_3;
6: 模糊查询: like _表示任意一个字符 %表示0到多个字符
select * from tab_3 where tname like '_1%';
7: 聚合函数: max min sum avg count
8: 排序: order by desc/asc
select * from tab_3 order by tid;
select * from tab_3 order by tid desc;
9: 分组: group by: 分组后只能获取组信息和聚合函数
select count(*) 人数,tsex 性别 from tab_3 group by tsex;
分组条件: having
select count(*) 人数,tsex 性别 from tab_3 group by tsex having count(*)>10;
10: 单表查询的语法格式
select 列
from 表
where 列条件
group by 分组列
having 组条件
order by 排序列
11: oracle中的两个伪列
rowid、rownum->所有的结果集都有这两个伪列
rowid: 是当前记录在tablespace的数据文件中的物理存储坐标
AAASNkAABAAAVJBAAA:tablespace+datafile+table+row+起始索引
rowid的作用:用于快速定位记录,提高查询效率
select t.*, rowid,rownum from tab_3 t where tid=810;
elect t.*, rowid,rownum from tab_3 t where rowid='AAASNkAABAAAVJBAAA';
rownum: 从数据库中查询的记录的顺序
rownum的作用: 分页
select tt.*
from (select t.*, rowid rid ,rownum rn
from tab_3 t
where rownum <=15 ) tt
where tt.rn >10;
==================================================
/*** 日期格式化 ***/
drop table tab_2;
create table tab_2(
tdate date
);
insert into tab_2 values(
to_date('2021/11/11 11:11:11','yyyy/mm/dd hh24:mi:ss')
)
select * from tab_2;
select 1+1 from tab_2;
select 1+1 from dual;
-- to_date(str,parten):把符合parten模式的字符串str转换为date
select to_date('2021/11/11 11:11:11','yyyy/mm/dd hh24:mi:ss') from dual;
-- 获取当前时间: sysdate、systimestamp
select sysdate from dual;
select systimestamp from dual;
-- to_char(date,parten): 把date数据转化为parten模式的字符串
select sysdate,to_char(sysdate,'yyyy/mm/dd hh24:mi:ss')from dual;--获取指定格式的字符串
select sysdate,to_char(sysdate,'yyyy/mm/dd D hh24:mi:ss') from dual;--含有星期的字符串
select sysdate,to_char(sysdate,'yyyy"年"mm"月"dd"号" hh24:mi:ss') from dual;--模式中有中文,必须加双引号
==================================================
-- *** oracle中的随机函数 ***
-- 随机数字[0,1)
select dbms_random.value from dual;
-- 随机数字[a,b]整数
select dbms_random.value(1,10) from dual;
-- 随机字符串
select dbms_random.string('u',10) from dual;-- 大写
select dbms_random.string('l',10) from dual;-- 小写
select dbms_random.string('a',10) from dual;-- 大小写
select dbms_random.string('x',10) from dual;-- 大写+数字
select dbms_random.string('p',10) from dual;-- 任意字符
-- 获取整数
select ceil(dbms_random.value(1,10)) from dual;-- 向上取整
select floor(dbms_random.value(1,10)) from dual;-- 向下取整
select round(dbms_random.value(1,10)) from dual;-- 四舍五入
select trunc(dbms_random.value(1,10)) from dual;-- 保留整数
-- 查询10到15的所有信息
select tt.*
from (select t.*, rowid rid ,rownum rn from tab_3 t where rownum <=15 ) tt
where tt.rn >10;
==================================================
/*** 多表查询 ***/
-- 创建表
create table tab_7(
tid int,
tname varchar(20),
tage int,
tscore number(4,1),
ttid int references tab_8(tid)
);
insert into tab_7 values(11,'韩雪',18,38.1,1);
insert into tab_7 values(12,'韩枫',19,48.1,2);
insert into tab_7 values(13,'叶晨',20,58.1,3);
insert into tab_7 values(14,'楚宣',21,68.1,null);
insert into tab_7 values(15,'楚灵',22,78.1,null);
create table tab_8(
tid int primary key,
treal_name varchar(20),
tsalary number(6,1)
);
insert into tab_8 values(1,'夕颜',10000);
insert into tab_8 values(2,'若曦',20000);
insert into tab_8 values(3,'月儿',30000);
alter table tab_7 rename to student;
alter table tab_8 rename to teacher;
-------------------------------------------------------------
1: 合并结果集:把两个列数相同,列类型相同的结果集,合并为一个结果集
-- 合并结果集 去除重复行
select tname,tscore from tab_7 union select treal_name,tsalary from tab_8;
-- 合并结果集 保留所有行
select tname,tscore from tab_7 union all select treal_name,tsalary from tab_8;
-------------------------------------------------------------
2: 连接查询:form后面两个表,对两个表进行笛卡尔积,根据条件去除垃圾行
-- 笛卡尔积:两个表的每个行之间互相见面
select * from tab_7,tab_8;
-- 内连接:只保留满足条件的笛卡尔积行
-- 方言格式
select * from tab_7 t7,tab_8 t8 where t7.ttid=t8.tid;
-- 标准格式
select * from tab_7 t7 inner join tab_8 t8 on t7.ttid=t8.tid
-- 外连接:保证某张表的完整性
-- 左外连接:保证左边表的完整性
select * from tab_7 t7 left join tab_8 t8 on t7.ttid=t8.tid;
-- 左外连接:oracle方言
select * from tab_7 t7,tab_8 t8 where t7.ttid=t8.tid(+);
-- 右外连接:保证右边表的完整性
select * from tab_7 t7 right join tab_8 t8 on t7.ttid=t8.tid;
-- 右外连接:oracle方言
select * from tab_7 t7,tab_8 t8 where t7.ttid(+)=t8.tid;
-------------------------------------------------------------
3: 子查询:select嵌套select
-- 1:子select出现在select后面
-- 获取所有学生+平均分的信息
select s.*,(select avg(tscore) from student) 平均分
from student s;
-- 把1并入列
select s.*,1 from student s;
-- 2:子select出现在form后面
-- 获取所有学生+平均分的信息
select s.*,sa.agt 平均分
from student s,(select avg(tscore) agt from student) sa;
-- 获取年龄大于10 小于100的学生
select *
from (select* from student where tage>10) s
where s.tage<100;
-- 3:子select出现在where后面
-- 获取大于平均分的学生的信息
select *
from student
where tscore>(select avg(tscore) from student);
索引:index
概念:
一种可以提升数据库查询效率的数据库对象
类似于:字典目录(按拼音查询/按偏旁查询/按笔画查询)
作用:快速定位数据
原理:定义索引时,会记录所有记录及其rowid
分类:
唯一性索引:
数据库为了提高检索效率自动创建的索引
主键约束列 + 唯一约束列
非唯一性约束:
程序员自己创建的索引
注意:索引会随着表记录的更改而自动更新
适合创建索引的列:
>列经常作为where条件
>列不能有大量的空值
>列取值范围应该很广
>表经常被访问,数据量很大,获取的记录数<总记录数的4%
不适合创建索引的列:
>表数据量小
>列不经常出现在where后面
>访问的数据量大于4%
>表记录经常更改
----------------------------------------------------------
create table stu(
sid int primary key,
sname varchar(20),
sage int,
sex char(3),
score float,
ss varchar(10) unique
);
-- 使用索引:索引不是让程序员使用的,是让数据库系统使用
-- 当索引列作为查询条件时,数据库可以通过索引快速获取符合条件的行记录
-- 创建索引:为指定表的指定类创建索引
create index index_score on stu(score);
-- 查看已有的索引
select *from user_indexes where table_name='STU';
-- 查看已有的索引及其对应的列
select * from user_ind_columns where table_name='STU';
-- 删除索引
drop index index_score;
常用函数
-- 1 转换函数
-- 1.1 to_char(date,pattern) 把date转换为指定格式的字符串
select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual;
-- 1.2 to_date(str,pattern) 把符合指定模式pattern的字符串str转换为日期对象
select to_date('2011-11-11 11:11:11','yyyy-mm-dd hh24:mi:ss') from dual;
-- 1.3 to_number(str,pattern) 把字符串转化为数字
select to_number('$11,111.22','$99,999,999.99') from dual;
----------------------------------------------------------------------
-- 2 数字函数
--2.1 取近似值的
-- floor:向下取整 ceil:向上取整 round:四舍五入 trunc:保留有效位数
select floor(3.5),ceil(3.5),round(3.5),trunc(3.5234,1),round(3.4567,2) from dual;
--2.2 绝对值
select abs(-2) from dual;
--2.3 幂运算
-- sqrt:根号 power(n,m):n的m次方
select sqrt(4),power(3,2) from dual;
--2.4 获取余数
select mod(3,2) from dual;
----------------------------------------------------------------------
-- 3 字符函数
-- 3.1 获取字符串长度
select length('abcde嘿嘿嘿') from dual;
-- 3.2 字符和字节转换
select ascii('岳'),chr(98) from dual;
-- 3.3 大小写转换
select upper('ABCabc'),lower('ABCabc') from dual;
-- 3.4 获取参数字串第一次出现的位置,3是下标 --索引从1开始
select instr('abc4bc123aa','a',3) from dual;
-- 3.5 替换
select replace('abc4bc123aa','a','0') from dual;
-- 3.6 截取字串:从2开始,截取四个字符
select substr('abc4bc123aa',2,4) from dual;
-- 3.7 去除两边的空格
select trim(' 111 22 ') from dual;
-- 3.8 字符串拼接
select concat('abc','bcbd'),'abc'||'123' from dual;
----------------------------------------------------------------------
-- 4 随机函数
-- 4.1 随机数字[0,1)
select dbms_random.value from dual;
-- 4.2 随机一个整数:正负不定
select dbms_random.random from dual;
-- 4.3 随机指定范围: 3-10
select dbms_random.value(3,10) from dual;
-- 4.4 随机字符串
select dbms_random.string('u',4) from dual;--大写字母
select dbms_random.string('l',4) from dual;--小写字母
select dbms_random.string('a',4) from dual;--大小写字母
select dbms_random.string('p',4) from dual;--任意字符
select dbms_random.string('x',4) from dual;--大写+数字
----------------------------------------------------------------------
-- 5 日期函数
-- 5.1 获取当前时间
select sysdate,systimestamp from dual;
-- 5.2 获取时间参数
select trunc(sysdate,'year'),trunc(sysdate,'month'),trunc(sysdate,'day') from dual;
select extract(year from sysdate),extract(month from sysdate),extract(day from sysdate) from dual;
select extract(hour from systimestamp),extract(minute from systimestamp),
extract(second from systimestamp) from dual;-- extract:抽取
-- 5.3 日期运算
select sysdate,sysdate+1 from dual;
select sysdate-(sysdate+1) from dual;
-- 5.4 月运算
select months_between(to_date('2019-11-12','yyyy-mm-dd'),to_date('2021-1-12','yyyy-mm-dd')) from dual;
----------------------------------------------------------------------
-- 6 其他函数
--null转换
--nvl:第一个参数不为空返回第一个参数,为空返回第二个参数
select nvl(1,2),nvl(null,2) from dual;
序列: sequence
-- 创建序列
create sequence seq_1;
-- 查看所有序列
select * from dba_sequences where sequence_owner='SYS';
-- 删除序列
drop sequence seq_1;
-- 使用sequence
-- nextval每获取一次,值+1一次
select seq_1.nextval from dual;
-- 一个select语句中nextval只自增一次
select seq_1.nextval,seq_1.nextval from dual;
-- currval获取当前值,sequence创建后不能先调用currval,没值
select seq_1.currval from dual;
-- 一般一个sequence只适用于一个表
create table stu(
sid int primary key,
sname varchar(20)
);
create sequence seq_stu;
insert into stu values(
seq_stu.nextval,
dbms_random.string('u',6)
);
select * from stu;
-- sequence完整定义
drop sequence seq_2;
create sequence seq_2
start with 10 /* 起始值,默认是1 */
maxvalue 50 /* 最大值 */
increment by 3 /* 步长 */
cache 5 /* 一次取5个 */
cycle /* 循环 */
select seq_2.nextval from dual;
视图:view
视图:把一个select的结果集作为一张虚拟表
视图的结构和数据是以基表为基础的
视图中不存储数据,只存储视图的定义和相关的rowid
视图作用:
1 提高查询效率,减少io操作
2 设置数据操作权限,防止隐私数据泄露
3 简化复杂sql语句的编写和编译过程
是否可以对视图进行增删改:
1 一般情况下 不能对视图进行增删改(视图中涉及多表查询、聚合函数...)
2 特殊情况下 可以对视图进行增删改,但操作的是基表中的数据
-----------------------------------------------------------
-- 查看列名
select * from user_tab_columns where table_name='STUDENT';
-- 创建视图
create view v_student_1 as select tname,tscore from student;
-- 查询当前用户的所有视图
select * from dba_views where owner='SYS';
-- 删除视图
drop view v_student_1;
-- 使用视图: 和表完全一样
select tname from v_student_1 where tname like '%楚%';
select * from v_student_1;
create view v_student_2 as select * from student where tscore>50;
select * from v_student_2;
insert into v_student_2 values(16,'千月',23,66,1);
create view v_student_3 as select tage,count(*) con,avg(tscore) agt from student group by tage;
-- 聚合函数视图不能插入数据,函数结果是个固定值,不能改变
事务
事务:描述一个业务逻辑的多个dml语句作为整体,要么都成功,要么都失败。
业务:张三给李四转账100
查询张三余额
查询李四账号
张三减去100
李四添加100
事务操纵:tcl:truncation control language
关键字: commit 、rollback、savepoint
drop table bankcard;
create table bankcard(
bid int primary key,
bname varchar(20),
balance decimal(9,1),
check (balance>=0)
);
create sequence seq_bank start with 1000;
insert into bankcard values(seq_bank.nextval,'叶晨',20);
insert into bankcard values(seq_bank.nextval,'楚宣',200);
insert into bankcard values(seq_bank.nextval,'楚灵',2000);
select * from bankcard;
select * from bankcard where bname='叶晨';
select * from bankcard where bname='楚宣';
update bankcard set balance=balance+100 where bname='叶晨';
update bankcard set balance=balance-100 where bname='楚宣';
------------------------------------------------------------
/*
实现事务操纵:需要多个dml语句作为一个整体:类似于java中方法
通过pl/sql块来封装sql语句
pl/sql块格式:
begin
sql语句1
sql语句2
...
exception
when others then
出现异常执行的sql语句
end;
*/
-- *** 实现叶晨给楚宣转账100 ***
begin
update bankcard set balance=balance+100 where bname='楚宣';
update bankcard set balance=balance-100 where bname='叶晨';
commit;/*事务提交:::没有出现异常*/
dbms_output.put_line('转账成功!');
exception
when others then
rollback; /*事务回滚*/
dbms_output.put_line('转账失败!');
end;
-- *** 实现叶晨给楚宣转账30 楚宣给楚灵转账100 ***
begin
update bankcard set balance=balance+30 where bname='楚宣';
update bankcard set balance=balance-30 where bname='叶晨';
savepoint aa; --设置一个savepoint用于回滚
update bankcard set balance=balance+100 where bname='楚灵';
update bankcard set balance=balance-100 where bname='楚宣';
commit;/*事务提交:::没有出现异常*/
dbms_output.put_line('转账成功!!!');
exception
when others then
rollback to savepoint aa; /*事务回滚到aa位置处*/
dbms_output.put_line('叶晨给楚宣转账30成功!楚宣给楚灵转账100失败!');
commit;
end;
面试题
*** char(n)、varchar(n)和varchar2(n)的区别 ***
相同之处:都是存储字符串的数据类型
不同之处:1 长度不同
char是固定长度
varchar和varchar2是可变长度
2 n的取值不同
char(n):n取值1到2000
varchar(n)和varchar2(n):n取值1到4000
3 char和varchar是sql标准
varchar2是方言,oracle特有的
4 varchar可以存储空字符串
varchar2通过null表示空字符串,节省空间
*** drop、delete、truncate的区别 ***
相同之处: 都可以实现删除表记录
不同之处:
drop是ddl语句:删除表结构和表记录,没有事务不能加条件
truncate是ddl语句:删除所有表记录,没有事务不能加条件
delete是dml语句:逐行删除表记录,有事务,可以回滚,可以加条件
*** oracle和mysql的区别 ***
1 oracle收费 功能强大 安全性高
mysql免费 满足基本功能 效率高
2 oracle事务默认手动提交
mysql事务默认自动提交
3 oracle没有auto_incrment自增约束 通过sequence实现自增
mysql有auto_incrment自增约束
4 oracle通过伪列rownum实现分页
mysql通过limit实现分页
5 oracle的char(n)/varchar(n)/varchar2(n)的n指的是字节
mysql的char(n)/varchar(n)的n指的是字符
6 oracle中无boolean类型
mysql中有boolean类型
*** 事务的四大特征 ***
分别是:原子性、一致性、隔离性、持久性
1.原子性(Atomicity):
原子性是指事物包含的所有操作,要么全部成功,要么全部失败回滚,因此事务的操作如果成功就必须要完全的应用到数据库,如果操作失败则不能对数据库有任何的影响。
*同一个事务关联的多个dml语句:要么都成功,要么都失败。
2.一致性(Consistency)
一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。举例来说,假设用户A和用户B两者的钱加起来一共是1000,那么不管A和B之间如何转账、转几次账,事务结束后两个用户的钱相加起来应该还得是1000,这就是事务的一致性。
*不管事务成功还是失败,事务执行前后的数据库整体状态必须一致。
3.隔离性(Isolation)
隔离性是当多个用户并发访问数据库时,比如同时操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。关于事务的隔离性数据库提供了多种隔离级别。
*两个事务之间互相隔离,互不影响
4.持久性(Durability)
持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。
*一旦事务执行成功,此事务对数据库的更改必须在数据库中实现。