目录
1.2.3.3.1 数据库管理系统的用途科学地组织和存储数据、高效地获取和维护数据
1.2.3.4 数据库系统(DBS (Database System,简称DBS))
前言
Oracle自用笔记复盘
一、Oracle 19c概述
1.1 Oracle的发展史
- Oracle是甲骨文公司的一款关系数据库管理系统,也是目前较流行的关系数据管理系统,在数据库领域中一直处于领先地位。该系统具有可移植性好、使用方便、功能强等特点。
- Oracle数据库自发布至今,也经历了一个从不稳定到稳定,从功能简单至强大的过程Oracle的每一次版本变迁,都具有里程碑意义。
- 小型:Access
- 中型:SQL Server、MySQL、TiDB
- 大型:Oracle、DB2、SyBase
特点:
- 可用性强
- 可扩展性强
- 数据安全性强
- 稳定性强
1.2 关系数据库基本理论
1.2.1 数据库的特点
- 永久存储
- 有组织
- 可共享
1.2.2 地位
数据库技术产生于六十年代末,是数据管理的有效技术,是计算机科学的重要分支数据库技术是信总系统的核心和基础,它的出现极大地促进了计算机应用向各行各业的渗透数据库已经成为每个人生活中不可缺少的部分。
1.2.3 数据库的4个基本概念
1.2.3.1 数据 (data)
- 是数据库中存储的基本对象
- 数据的定义:描述事物的符号记录
- 数据的种类:数字、文字、图形、图像、音频、视频、学生的档案记录等
- 数据的含义称为数据的语义数据与其语义是不可分的。
- 例如 93是一个数据
语义1:学生某门课的成绩
语义2:某人的体重
语义3:计算机系2013级学生人数
语义4:请同学给出
1.2.3.2 数据库(Database)
- 数据库(Database,简称DB)是长期储存在计算机内、有组织的、可共享的大量数据的集合。
1.2.3.2 .1 数据库的基本特征
- 数据按一定的数据模型组织、描述和储存
- 可为各种用户共享冗余度较小
- 数据独立性较高
- 易扩展
1.2.3.3 数据库管理系统(DBMS)
- 位于用户与操作系统之间的一层数据管理软件
- 是基础软件,是一个大型复杂的软件系统
1.2.3.3.1 数据库管理系统的用途
科学地组织和存储数据、高效地获取和维护数据
1.2.3.3.2 数据库管理系统的主要功能
(1)数据定义功能
- 提供数据定义语言(DDL)
- 定义数据库中的数据对象
(2)数据组织、存储和管理
- 分类组织、存储和管理各种数据
- 确定组织数据的文件结构和存取方式
- 实现数据之间的联系
- 提供多种存取方法提高存取效率
(3)数据操纵功能
- 提供数据操纵语言(DML)
- 实现对数据库的基本操作(查询、插入、删除和修改)
(4)数据库的事务管理和运行管理
- 数据库在建立、运行和维护时由数据库管理系统统一管理和控制
- 保证数据的安全性、完整性、多用户对数据的并发使用
- 发生故障后的系统恢复
(5)数据库的建立和维护功能
- 数据库初始数据的装载和转换
- 数据库转储、恢复功能
- 数据库的重组织
- 性能监视、分析等
(6)其它功能
- 数据库管理系统与网络中其它软件系统的通信
- 数据库管理系统系统之间的数据转换
- 异构数据库之间的互访和互操作
1.2.3.4 数据库系统(DBS (Database System,简称DBS))
1.2.3.4.1 数据库系统的构成
- 数据库
- 数据库管理系统(及其应用开发工具)
- 应用程序
- 数据库管理员
1.2.3.4.2 数据管理技术的产生和发展
1.2.3.4.3 什么是数据管理
- 对数据进行分类、组织、编码、存储、检索和维护
- 数据处理的中心问题
1.2.3.4.4 数据管理技术的发展过程
- 人工管理阶段(20世纪50年代中之前)
- 文件系统阶段(20世纪50年代末--60年代中)
- 数据库系统阶段(20世纪60年代末--现在)
1.2.3.4.5 数据管理技术的发展动力
- 应用需求的推动
- 计算机硬件的发展
- 计算机软件的发展
1.2.3.4.6 数据库系统的特点
- 数据结构化
- 数据的共享性高,冗余度低且易扩充
- 数据独立性高
- 数据由数据库管理系统统一管理和控制
1.2.3.4.7 数据结构化
数据的整体结构化是数据库的主要特征之一
(1)整体结构化
- 不再仅仅针对某一个应用,而是面向全组织
- 不仅数据内部结构化,整体是结构化的,数据之间具有联系
- 数据记录可以变长
- 数据的最小存取单位是数据项
1.2.3.4.8 数据的共享性高,冗余度低且易扩充
数据面向整个系统,可以被多个用户、多个应用共享使用
数据共享的好处
- 减少数据冗余,节约存储空间
- 避免数据之间的不相容性与不一致
- 性使系统易于扩充
1.2.3.4.9 数据独立性高
(1)物理独立性
- 指用户的应用程序与数据库中数据的物理存储是相互独立的。当数据的物理存储改变了,应用程序不用改变。
(2)逻辑独立性
- 指用户的应用程序与数据库的逻辑结构是相互独立的。数据的逻辑结构改变了,应用程序不用改变
(3)数据独立性
- 由数据库管理系统的二级映像功能来保证
1.2.3.4.10 数据由数据管理系统统一管理和控制
数据库管理系统提供的数据控制功能
(1)数据的安全性(Security)
保护数据以防止不合法的使用造成的数据的泄密和破坏
(2)数据的完整性(Integrity)
检查保证数据的正确性、有效性和相容性。
(3))并发(Concurrency)
控制对多用户的并发操作加以控制和协调,防止相互干扰而得到错误的结果
(4)数据库恢复(Recovery)
将数据库从错误状态恢复到某一已知的正确状态
1.2.4 小结
- 数据库是长期存储在计算机内有组织的大量的共享的数据集合
- 可以供各种用户共享,具有最小冗余度和较高的数据独立性
- 数据库管理系统在数据库建立、运用和维护时对数据库进行统一控制,以保证数据的完整性、安3全性,并在多用户同时使用数据库时进行并发控制,在发生故障后对数据库进行恢复。
1.3 数据模型
- 数据模型是对现实世界数据特征的抽象
- 通俗地讲数据模型就是现实世界的模拟。
1.3.1 数据模型应满足三方面要求:
- 能比较真实地模拟现实世界
- 容易为人所理解
- 便于在计算机上实现
数据模型是数据库系统的核心和基础
两类数据模型
1.3.2 客观对象的抽象过程---两步抽象
现实世界中的客观对象抽象为概念模型
- 将现实世界抽象为信息世界
把概念模型转换为某一数据库管理系统支持的数据模型
- 将信息世界转换为机器世界
数据模型分为两类(两个不同的层次)
(1)概念模型也称信息模型,它是按用户的观点来对数据和信息建模,用于数据库设计。
(2)逻辑模型和物理模型
- 逻辑模型主要包括网状模型、层次模型、关系型、面向对象数据模型、对象关系数据模型半结构化数据模型等。按计算机系统的观点对数据建模,用于DBMS实现
- 物理模型是对数据最底层的抽象,描述数据在系统内部的表示方式和存取方法,在磁盘或磁带上的存储方式和存取方法。
1.3.3 客观对象的抽象过程---两步抽象
- 现实世界中的客观对象抽象为概念模型
将现实世界抽象为信息世界
- 把概念模型转换为某一数据库管理系统支持的数据模型
将信息世界转换为机器世界
1.3.4 概念模型
(1)概念模型的用途
- 概念模型用于信息世界的建模
- 是现实世界到机器世界的一个中间层次
- 是数据库设计的有力工具
- 数据库设计人员和用户之间进行交流的语言
(2)对概念模型的基本要求
- 较强的语义表达能力
- 简单、清晰、易于用户理解
- 信息世界中的基本概念
- 概念模型的一种表示方法:实体-联系方法
1.3.5 信息世界中的基本概念
(1)实体(Entity)
- 客观存在并可相互区别的事物称为实体。可以是具体的人、事、物或抽象的概念
(2)属性(Attribute)
- 实体所具有的某一特性称为属性。一个实体可以由若干个属性来刻画。
(3)码(Key)
- 唯一标识实体的属性集称为码。
(4)实体型(Entity Type)
- 用实体名及其属性名集合来抽象和刻画同类实体称为实体型
(5)实体集(Entity Set)
- 同一类型实体的集合称为实体集
(6)联系(Relationship)
- 现实世界中事物内部以及事物之间的联系在信息世界中反映为实体(型)内部的联系和实体(型)之间的联系,
- 实体内部的联系通常是指组成
- 实体的各属性之间的联系
- 实体之间的联系通常是指不同
- 实体集之间的联系实体之间的联系有一对一、一对多和多对多等多种类型
1.3.6 实体-联系方法
实体-联系方法(Entity-Relationship Approach)
- 用E-R图来描述现实世界的概念模型
- E-R方法也称为E-R模型
1.3.7 数据操作
数据操作
- 对数据库中各种对象(型)的实例(值)允许执行的操作的集合,包括操作及有关的操作规则
数据操作的类型
- 查询
- 更新(包括插入、删除、修改)
数据模型对操作的定义操作的确切含义
- 操作符号
- 操作规则(如优先级)
- 实现操作的语言
数据操作是对系统动态特性的描述
1.3.8 数据的完整性约束条件
- 一组完整性规则的集合
- 完整性规则:给定的数据模型中数据及其联系所具有的制约和依存规则
- 用以限定符合数据模型的数据库状态以及状态的变化,以保证数据的正确、有效和相容
1.3.9 常用的数据模型
- 层次模型(Hierarchical Model)
- 网状模型(Network Model)
- 关系模型(Relational Model)
- 面向对象数据模型对象关系数据模型(Object Oriented Data Model)
- 半结构化数据模型(Semistruture Data Model)
(1)层次模型
- 层次模型是数据库系统中最早出现的数据模型
- 层次数据库系统的典型代表是IBM公司的IMS(Information Management System)数据库管理系统
- 层次模型用树形结构来表示各类实体以及实体间的联系
层次模型的数据结构
满足下面两个条件的基本层次联系的集合为层次模型
- 有且只有一个结点没有双亲结点,这个结点称为根结点
- 根以外的其它结点有且只有一个双亲结点
层次模型中的几个术语
根结点,双亲结点,兄弟结点,叶结点
层次模型的特点
- 结点的双亲是唯一的
- 只能直接处理一对多的实体联系每个记录类型可以定义一个排序字段,也称为码字段
- 任何记录值只有按其路径查看时,才能显出它的全部意义
- 没有一个子女记录值能够脱离双亲记录值而独立存在
层次模型的完整性约束条件
- 无相应的双亲结点值就不能插入子女结点值
- 如果删除双亲结点值,则相应的子女结点值也被同时删除
- 更新操作时,应更新所有相应记录,以保证数据的一致性
层次模型的优缺点
优点
- 层次模型的数据结构比较简单清晰
- 查询效率高,性能优于关系模型,不低于网状模型
- 层次数据模型提供了良好的完整性支持
缺点
- 结点之间的多对多联系表示不自然
- 对插入和删除操作的限制多,应用程序的编写比较复杂
- 查询子女结点必须通过双亲结点
- 层次命令趋于程序化
(2)网状模型
网状数据库系统采用网状模型作为数据的组织方式
满足下面两个条件的基本层次联系的集合:
- 允许一个以上的结点无双亲
- 一个结点可以有多于一个的双亲
网状模型的数据结构
- 网状模型中子女结点与双亲结点的联系可以不唯一
- 要为每个联系命名,并指出与该联系有关的双亲记录和子女记录
网状模型的优缺点
优点
- 能够更为直接地描述现实世界,如一个结点可以有多个双亲
- 具有良好的性能,存取效率较高
缺点
- 结构比较复杂,而且随着应用环境的扩大,数据库的结构就变得越来越复杂,不利于最终用户掌握DDL、DML语言复杂,用户不容易使用
- 记录之间联系是通过存取路径实现的,用户必须了解系统结构的细节
(3)关系模型
- 关系数据库系统采用关系模型作为数据的组织方式
- 1970年美国IBM公司San Jose研究室的研究员E.F.Codd首次提出了数据库系统的关系模型计算机厂商新推出的数据库管理系统几乎都支持关系模型
关系模型的数据结构
关系(Relation)
- 一个关系对应通常说的一张表
元组(Tuple)
- 表中的一行即为一个元组
属性(Attribute)
- 表中的一列即为一个属性,给每一个属性起一个名称即属性名
主码(Key)
- 也称码键。表中的某个属性组,它可以唯一确定一个元组
域(Domain)
- 是一组具有相同数据类型的值的集合。属性的取值范围来自某个域
分量
- 元组中的一个属性值
关系模式:对关系的描述
- 关系名(属性1,属性2,…,属性n)
- 学生(学号,姓名,年龄,性别,系名,年级)
关系必须是规范化的,满足一定的规范条件
- 最基本的规范条件:关系的每一个分量必须是一个不可分的数据项,不允许表中还有表下图中工资和扣除是可分的数据项,不符合关系模型要求
术语对比
关系术语 | 一般表格的术语 |
关系名 | 表名 |
关系模式 | 表头(表格的描述) |
关系 | (一张)二维表 |
元组 | 记录或行列 |
属性 | 列 |
属性名 | 列名 |
属性值 | 列值 |
分量 | 一条记录中的一个列值 |
非规范关系 | 表中有表(大表中嵌有小表) |
关系模型的操纵与完整性约束
数据操作是集合操作,操作对象和操作结果都是关系
- 查询
- 插入
- 删除
- 更新
存取路径对用户隐蔽,用户只要指出“干什么”,不必详细说明“怎么干
关系的完整性约束条件
- 实体完整性
- 参照完整性
- 用户定义的完整性
关系模型的优缺点
优点
- 建立在严格的数学概念的基础上
- 概念单一
实体和各类联系都用关系来表示
对数据的检索结果也是关系
关系模型的存取路径对用户透明
- 具有更高的数据独立性,更好的安全保密性
- 简化了程序员的工作和数据库开发建立的工作
缺点
- 存取路径对用户透明,查询效率往往不如格式化数据模型
- 为提高性能,必须对用户的查询请求进行优化,增加了开发数据库管理系统的难度
二、安装Oracle19c
具体安装包贴在资源包里,具体安装过程如下:
安装完成可以查看到已经有服务了
在“cmd”窗口命令行中测试版本,输入:sqlplus system/“自己设置的密码”
三、Oracle体系结构
3.1 概述
用户进程和服务器进程的关系
3.2 存储结构
3.2.1 逻辑存储结构
3.2.1.1 数据块
- 数据块是Oracle逻辑存储结构中的最小的逻辑单位
- 一个数据库块对应一个或者多个物理块,大小由参数DB_BLOCK_SIZE决定
- 数据块的结构包括块头和存储区的两个部分
3.2.1.2 数据区
- 数据区是由连续的数据块结合而成的
- 数据区是Oracle存储分配的最小单位
3.2.1.3 段
- 数据段:存储表中所有数据
- 索引段:存储表上最佳查询的所有索引数据
- 临时段:存储表排序操作期间建立的临时表的数据
- 回滚段:存储修改之前的位置和值
3.2.1.4 表空间
- 表空间是数据库的最大逻辑划分区域
- 一个表空间由一个或多个数据文件组成,一个数据文件只属于一个表空间
- 表空间的大小是它所对应的数据文件大小的总和
3.2.1.5 默认创建的表空间
- 系统表空间
- 辅助表空间
- 撤销表空间
- 用户表空间
3.2.2 物理存储结构
物理结构包含三种数据文件
- 控制文件
- 数据文件
- 重做日志文件
3.2.2.1 数据文件.DBF
- 系统数据文件(SYSTEM01.DBF和SYSAUX01.DBF)
- 回滚数据文件(UNDOTBS01.DBF)
- 用户数据文件(USERS01.DBF、TBSP_1.DBF)
- 临时数据文件(TEMPO2.DBF)
3.2.2.2 控制文件 .CTL
- 是数据库中最小的文件
- 是数据库中最重要的文件
3.2.2.3 日志文件 .LOG
- 重做日志文件:记录所有的数据变化、提供恢复机制
- 归档日志文件:重做日志文件的历史备份,归档模式、非归档模式
3.2.2.4 其他文件
- 服务器参数文件(orcl.ora)
- 密码文件(PWDorcl.ora)
- 警告文件(alert_orcl.log)
- 跟踪文件
3.3 服务器结构
Oracle服务器主要有以下部分组成
- 实例
- 数据库
- 程序全局区(PQA)前台进程
3.3.1 系统全局区SGA
3.3.2 高速数据缓冲区
作用:用来存放Oracle系统最近访问过的数据块
- 经常或最近被访问的数据块会被放置到高速数据缓冲区的前端,不经常被访问的数据块会被放置到高速数据缓冲区的后端
3.3.3 共享池
作用:存储最近执行过的SQL语句和最近使用过的数据定义
共享池包含
- 库高速缓冲区
- 字典高速缓冲区
3.3.4 程序全局区PGA
程序全局区PGA又称作用户进程全局区。可以把代码、全局变量和数据结构都存储在其中每个Oracle服务器进程只拥有自己的那部分PGA资源
程序全局区由两部分组成
- 私有SQL区
- 会话区
3.3.5 前台进程
- 用户进程:使用SQL Plus连接成功后生成。包含两个重要概念:连接和会话
- 服务器进程:处理用户会话过程中的SQL语句和SQLPlus命令
3.3.6 后台进程
- 数据写入进程
- 检查点进程
- 日志写入进程
- 归档进程
3.4 数据字典
数据字典是Oracle存储数据库内部信息的地方,描述了数据库内部的运行和管理情况,Oracle数据字典的名称由前缀和后缀组成,使用下划线“_“连接
- dba_:包含数据库实例的所有对象信息
- v$_:当前实例的动态视图,包含系统管理和系统优化等使用的视图
- user_:记录用户的对象信息
- gV_:分布式环境下所有实例的动态视图,包含系统管理和系统优化使用的视图
- all_:记录用户的对象信息及被授权访问的对象信息。
3.4.1 基本的数据字典
字典名称 | 说 明 |
---|---|
DBA TABLES | 所有用户的所有表的信息 |
DBA TAB COLUMNS | 所有用户的表的字段信息 |
DBA VIEWS | 所有用户的所有视图信息 |
DBA SYNONYMS | 所有用户的同义词信息 |
DBA SEQUENCES | 所有用户的序列信息 |
DBA_CONSTRAINTS | 所有用户的表的约束信息 |
DBA INDEXES | 所有用户的表的索引简要信息所有用户的 |
DBA IND COLUMNS | 索引的字段信息 |
DBA_TRIGGERS | 所有用户的触发器信息 |
DBA SOURCES | 所有用户的存储过程信息 |
DBA SEGMENTS | 所有用户的段的使用空间信息 |
DBA EXTENTS | 所有用户的段的扩展信息 |
DBA OBJECTS | 所有用户对象的基本信息 |
3.4.2 常用动态性能视图
视图名称 | 说 明 |
---|---|
V$ FIXED TABLE | 显示当前发行的固定对象的说明 |
V$ INSTANCE | 显示当前实例信息 |
V$ LATCH | 显示锁存器的统计数据 |
V$ LIBRARYCACHE | 显示有关库缓存性能的统计数据 |
V$ ROLLSTAT | 显示联机的回滚段的名字 |
V$ ROWCACHE | 显示活动数据字典的统计 |
V$SGA | 显示有关系统全局区的总结信息 |
V$ SGASTAT | 显示有关系统全局区的详细信息 |
V$SORT USAGE | 显示临时段的大小及会话 |
V$SQLAREA | 显示SQL区的SQL信息 |
VSSQLTEXT | 显示在SGA中属于共享游标的SQL语句内容 |
V$STSSTAT | 显示基本的实例统计数据 |
V$SYSTEM EVENT | 显示一个事件的总计等待时间 |
V$WAITSTAT | 显示块竞争统计数据 |
四、DBeaver Community安装
从官网download下载对应安装包。同样,相关资源包也会上传到主页
安装默认下一步,选择对应路径安装即可。
打开软件
五、SQL语言基础
5.1 概述
.SQL(Structured Query Language)
结构化查询语言,是关系数据库的标准语言SQL是一个通用的、功能极强的关系数据库语言
5.1.1 SQL的特点
综合统一
- 集数据定义语言(DDL),数据操纵语言(DML),数据控制语言(DCL)功能于一体
- 可以独立完成数据库生命周期中的全部活动:
- 定义和修改、删除关系模式,定义和删除视图,插入数据,建立数据库;
- 对数据库中的数据进行查询和更新:
- 数据库重构和维护
- 数据库安全性、完整性控制,以及事务控制
- 嵌入式SQL和动态SQL定义
- 用户数据库投入运行后,可根据需要随时逐步修改模式,不影响数据库的运行
- 数据操作符统一
5.1.2 高度非过程化
- 非关系数据模型的数据操纵语言“面向过程必须指定存取路径SQL只要提出“做什么”,无须了解存取路径。
- 存取路径的选择以及SQL的操作过程由系统自动完成
5.1.3 面向集合的操作方式
非关系数据模型采用面向记录的操作方式,操作对象是一条记录
SQL采用集合操作方式
- 操作对象、查找结果可以是元组的集合
- 一次插入、删除、更新操作的对象可以是元组的集合
5.1.4 以同一种语法结构提供多种使用方式
- SQL是独立的语言,能够独立地用于联机交互的使用方式SQL又是嵌入式语言
- SQL能够嵌入到高级语言(例如C,C++,Java)程序中,供程序员设计程序时使用
5.1.5 语言简洁,易学易用
SQL功能极强,完成核心功能只用了9个动词
SQL功能 | 动词 |
---|---|
数据查询 | SELECT |
数据定义 | CREATE,DROP,ALTER |
数据操纵 | INSERT,UPDATE,DELETE |
数据控制 | GRANT,REVOKE |
基本表
- 本身独立存在的表
- SQL中一个关系就对应一个基本表
- 一个(或多个)基本表对应一个存储文件
- 一个表可以带若干索引
存储文件
- 逻辑结构组成了关系数据库的内模式
- 物理结构对用户是隐蔽的
视图
- 从一个或几个基本表导出的表
- 数据库中只存放视图的定义而不存放视图对应的数据
- 视图是一个虚表
- 用户可以在视图上再定义视图
5.2 数据定义
5.2.1 用户模式
在Oracle数据库中,为了便于管理用户创建的数据库对象(如数据表、索引、视图等),引入了模式的概念,某个用户创建的数据库对象都属于该用户模式。模式=用户,一个模式不能访问其他模式里面的内容
怎么创建模式?
5.3 数据类型
- SQL中域的概念用数据类型来实现
- 定义表的属性时需要指明其数据类型及长度
选用哪种数据类型
- 取值范围
- 要做哪些运算
数据类型 | 含义 |
CHAR(n),CHARACTER(n) | 长度为n的定长字符串 |
VARCHAR(n), CHARACTERVARYING(n) | 最大长度为n的变长字符串 |
CLOB | 字符串大对象 |
BLOB | 二进制大对象 |
INT, INTEGER | 长整数(4字节) |
SMALLINT | 短整数(2字节) |
BIGINT | 大整数(8字节) |
NUMERIC(P, d) | 定点数,由P位数字(不包括符号、小数点)组成,小数后面有d位数字 |
DECIMAL(P, d), DEC(P, d) | 同NUMERIC |
REAL | 取决于机器精度的单精度浮点数 |
DOUBLE PRECISION | 取决于机器精度的双精度浮点数 |
FLOAT(n) | 可选精度的浮点数,精度至少为n位数字 |
BOOLEAN | 逻辑布尔量 |
DATE | 日期,包含年、月、日,格式为YYYY-MM-DD |
TIME | 时间,包含一日的时、分、秒,格式为HH:MM:SS |
TIMESTAMP | 时间戳类型 |
INTERVAL | 时间间隔类型 |
5.4 表的建立和查询
定义基本表
CREATE TABLE<表名>
(<列名><数据类型>[<列级完整性约束条件>]
[,<列名><数据类型>[<列级完整性约束条件>]]…
[,<表级完整性约束条件>]):
- <表名>:所要定义的基本表的名字
- <列名>:组成该表的各个属性(列)
- <列级完整性约束条件>:涉及相应属性列的完整性约束条件
- <表级完整性约束条件>:涉及一个或多个属性列的完整性约束条件
- 如果完整性约束条件涉及到该表的多个属性列,则必须定义在表级上,否则既可以定义在列级也可以定义在表级。
5.4.1 添加表
-- 建立“学生"表Student。学号是主码,姓名取值唯一(注释是:--+空格)
CREATE TABLE student(
sno char(9) PRIMARY KEY,
sname char(20) UNIQUE,
ssex char(2),
sage SMALLINT,
sdept char(20)
);
-- [例3.6]建立一个"课程”表Course
CREATE TABLE course(
cno char(4) PRIMARY KEY,
cname char(40),
cpno char(4),
ccredit SMALLINT,
FOREIGN key(cpno) REFERENCES course(cno)
);
-- [例3.7] 建立一个学生选课表SC
CREATE TABLE sc(
sno char(9),
cno char(4),
grade SMALLINT,
PRIMARY KEY(sno,cno),
FOREIGN KEY (sno) REFERENCES student(sno),
FOREIGN KEY (cno) REFERENCES course(cno)
);
5.4.2 修改基本表
ALTER TABLE<表名)
[ADD[COLUMN]<新列名><数据类型>[完整性约束 ]]
[ADD<表级完整性约束>]
[DROP[COLUMN]<列名>[CASCADE|RESTRICT]][DROP CONSTRAINT<完整性约束名>[RESTRICTCASCADE]][ALTER COLUMN〈列名><数据类型>]
-- 建立“学生"表Student。学号是主码,姓名取值唯一(注释是:--+空格)
CREATE TABLE student(
sno char(9) PRIMARY KEY,
sname char(20) UNIQUE,
ssex char(2),
sage SMALLINT,
sdept char(20)
);
-- [例3.6]建立一个"课程”表Course
CREATE TABLE course(
cno char(4) PRIMARY KEY,
cname char(40),
cpno char(4),
ccredit SMALLINT,
FOREIGN key(cpno) REFERENCES course(cno)
);
-- [例3.7] 建立一个学生选课表SC
CREATE TABLE sc(
sno char(9),
cno char(4),
grade SMALLINT,
PRIMARY KEY(sno,cno),
FOREIGN KEY (sno) REFERENCES student(sno),
FOREIGN KEY (cno) REFERENCES course(cno)
);
-- [例3.8]向Student表增加“入学时间"列,其数据类型为日期型
ALTER TABLE student ADD s_entrance DATE;
-- [例3.9]将年龄的数据类型由字符型(假设原来的数据类型是字符型) 改为整数。
ALTER TABLE student MODIFY sage int;
-- [例3.10]增加课程名称必须取唯一值的约束条件。
ALTER TABLE course ADD UNIQUE(cname)
5.4.3 数据查询
SELECT [ALL|DISTINCT] <目标列表达式>[,<目标列表达式>]…
FROM <表名或视图名>[,<表名或视图名>]…(SELECT 语句)[AS]<别名)
[WHERE <条件表达式>
[GROUP BY<列名1>[HAVING<条件表达式>]]
[ORDER BY<列名2>[ASC|DESC ]];
首先添加数据
GRANT dba TO scott;
INSERT INTO course VALUES ('1','数据库',NULL,4);
INSERT INTO course VALUES ('2','数学',NULL,2);
INSERT INTO course VALUES ('3','信息系统','1',4);
INSERT INTO course VALUES ('4','操作系统','2',3);
INSERT INTO course VALUES ('5','数据结构','1',4);
INSERT INTO course VALUES ('6','数据处理',NULL,2);
INSERT INTO course VALUES ('7','PASCAL语言','6',4);
INSERT INTO course VALUES ('8','DBADesign',NULL,3);
INSERT INTO student(sno,sname,ssex,sage,sdept) VALUES ('201215121','李勇','m',26,'CS');
INSERT INTO student(sno,sname,ssex,sage,sdept) VALUES ('201215122','刘晨','f',19,'CS');
INSERT INTO student(sno,sname,ssex,sage,sdept) VALUES ('201215123','王敏','f',19,'MA');
INSERT INTO student(sno,sname,ssex,sage,sdept) VALUES ('201215125','刘辰','m',21,'IS');
INSERT INTO student(sno,sname,ssex,sage,sdept) VALUES ('201215138','陈冬东','m',19,NULL);
INSERT INTO student(sno,sname,ssex,sage,sdept) VALUES ('201215168','陈冬南','f',29,'MA');
INSERT INTO sc VALUES ('201215125','1',87);
INSERT INTO sc VALUES ('201215121','1',90);
INSERT INTO sc VALUES ('201215122','3',95);
INSERT INTO sc VALUES ('201215125','2',88);
- SELECT子句:指定要显示的属性列
- FROM子句:指定查询对象(基本表或视图)WHERE子句:指定查询条件
- GROUP BY子句:对查询结果按指定列的值分组,该属性列值相等的元组为一个组。通常会在每组中作用聚集函数。
- HAVING短语:只有满足指定条件的组才予以输出
- ORDER BY子句:对查询结果表按指定列值的升序或降序排序
-- [例3.16]查询全体学生的学号与姓名。
SELECT sno,sname FROM student
-- [例3.17]查询全体学生的姓名、学号、所在系
SELECT sno,sname,sdept FROM student
-- [例3.18]查询全体学生的详细记录
SELECT sno,sname,ssex,sage,sdept FROM student
-- [例3.19]查全体学生的姓名及其出生年份
SELECT sname,2024-sage FROM student
-- [例3.20]查询全体学生的姓名、出生年份和所在的院系,要求用小写字母表示系名。
-- 并添加合适的标题
SELECT sname AS 姓名,2024-sage AS 出生年份,LOWER(sdept) AS 所在院系 FROM student
-- 同理,去掉AS一样的效果
SELECT sname 姓名,2024-sage 出生年份,LOWER(sdept) 所在院系 FROM student
-- 消除取值重复的行,如果没有指定DISTINCT关键词,则缺省为ALL
-- [例3.21]查询选修了课程的学生学号
SELECT DISTINCT sno FROM sc
查询满足条件的元组
常用的查询条件
查询条件 | 谓 词 |
比 较 | <,>=,<=,!=,<>,!>,!<;NOT+上述比较运算符 |
确定范围 | BETWEEN AND,,NOT BETWEEN AND |
确定集合 | IN, NOT IN |
字符匹配 | LIKE【%(多个字符),_(单个字符)】, NOT LIKE |
空值 | IS NULL, IS NOT NULL |
多重条件(逻辑运算) | AND,OR, NOT |
-- [例3.22]查询计算机科学系全体学生的名单。
SELECT * FROM student WHERE sdept='CS'
-- [例3.23]查询所有年龄在20岁以下的学生姓名及其年龄。
SELECT sname,sage FROM student WHERE sage<20
-- [例3.24]查询考试成绩有及格的学生的学号。
SELECT DISTINCT sno FROM SC WHERE grade>=60
-- [例3.25]查询年龄在20~23岁(包括20岁和23岁)之间的学生的姓名、系别和年龄
SELECT sname,sage,sdept FROM student WHERE sage>=20 AND sage<=23
--BETWEEN 和 AND 就是大于等于 或者小于等于
SELECT sname,sage,sdept FROM student WHERE sage BETWEEN 20 AND 23
-- [例3.26]查询年龄不在20~23岁之间的学生姓名、系别和年龄
SELECT sname,sage,sdept FROM student WHERE sage NOT BETWEEN 20 AND 23
--或者
SELECT sname,sage,sdept FROM student WHERE sage<20 OR sage>23
-- [例3.27]查询计算机科学系(CS)、数学系(MA)和信息系(IS)学生的姓名和性别。
SELECT sname,ssex FROM student WHERE sdept='CS' OR sdept='MA' OR sdept='IS'
-- IN就是指定里面的一个集合
SELECT sname,ssex FROM student WHERE sdept IN ('CS','MA','IS')
-- [例3.28]查询既不是计算机科学系、数学系的学生的姓名和性别。
SELECT sname,ssex FROM student WHERE sdept!='CS' AND sdept!='MA'
SELECT sname,ssex FROM student WHERE sdept NOT IN ('CS','MA')
-- [例3.29]查询学号为201215121的学生的详细情况。
SELECT * FROM student WHERE sno='201215121'
--LIKE 就是等于的意思
SELECT * FROM student WHERE sno LIKE '201215121'
-- [例3.30]查询所有姓刘学生的姓名、学号和性别。
-- %:表示后面还有多个字符 _:代表一个字符
SELECT sno,sname,ssex FROM student WHERE sname LIKE '刘%'
-- [例3.36]某些学生选修课程后没有参加考试,所以有选课记录,但没有考试成绩。
查询缺少成绩的学生的学号和相应的课程号。
SELECT sno,cno FROM sc WHERE grade IS NULL
-- [例3.37]查所有有成绩的学生学号和课程号
SELECT sno,cno FROM sc WHERE grade IS NOT NULL
-- [例3.38] 查询计算机系年龄在20岁以下的学生姓名
SELECT sname FROM student WHERE sdept='CS' AND sage<20
ORDER BY子句
- 可以按一个或多个属性列排序
- 升序:ASC;降序:DESC;缺省值为升序
- 对于空值,排序时显示的次序由具体系统实现来决定
聚集函数
统计元组个数
- COUNT (*)
统计一列中值的个数
- COUNT([DISTINCT|ALL]<列名>)
计算一列值的总和(此列必须为数值型)
- SUM([DISTINCTIALL]<列名>)
计算一列值的平均值(此列必须为数值型)
- AVG([DISTINCT|ALL]<列名>)
求一列中的最大值和最小值MAX
- ([DISTINCT|ALL]<列名>)MIN([DISTINCT|ALL]<列名>)
-- [例3.39]查询选修了3号课程的学生的学号及其成绩,查询结果按分数降序排列。
-- 默认升序
SELECT sno,grade FROM sc WHERE cno='3' ORDER BY grade
-- 同上述一样
SELECT sno,grade FROM sc WHERE cno='3' ORDER BY grade ASC
--降序
SELECT sno,grade FROM sc WHERE cno='3' ORDER BY grade DESC
-- [例3.40]查询全体学生情况,查询结果按所在系的系号升序排列,同一系中的学生按年龄降序排列。
SELECT * FROM student ORDER BY sdept,sage DESC
-- [例3.41]查询学生总人数。
SELECT COUNT(*) FROM student
-- [例3.42]查询选修了课程的学生人数。
SELECT COUNT(DISTINCT sno) FROM sc
-- [例3.43]计算3号课程的学生平均成绩。
SELECT AVG(grade) FROM sc WHERE cno='3'
-- [例3.44]查询选修3号课程的学生最高分数。
SELECT MAX(grade) FROM sc WHERE cno='3'
-- [例3.45]查询学生201215125选修课程的总学分数。
SELECT SUM(course.ccredit) FROM sc,course WHERE sc.cno=course.cno AND sno='201215125'
GROUP BY子句
细化聚集函数的作用对象
- 如果未对查询结果分组,聚集函数将作用于整个查询结果
- 对查询结果分组后,聚集函数将分别作用于每个组
- 按指定的一列或多列值分组,值相等的为一组
-- [例3.46]求各个课程号及相应的选课人数。
SELECT cno,COUNT(sno) FROM sc GROUP BY cno
-- [例3.47]查询选修了2门以上课程的学生学号
SELECT sno FROM sc GROUP BY sno HAVING COUNT(*)>=2
-- [例3.48]查询平均成绩大于等于90分的学生学号和平均成绩
SELECT sno,avg(grade) FROM sc GROUP BY sno HAVING avg(grade)>=90
HAVING短语与WHERE子句的区别:(注:GROUP BY不能在WHERE后面写)
- 作用对象不同
- WHERE子句作用于基表或视图,从中选择满足条件的元组
- HAVING短语作用于组,从中选择满足条件的组。
5.4.4 连接查询
连接查询:同时涉及两个以上的表的查询
连接条件或连接谓词:用来连接两个表的条件
一般格式:
[<表名1>.]<列名1><比较运算符>[<表名2>.]<列名2>
[<表名1>.]<列名1>BETWEEN[<表名2>.]<列名2>AND[<表名2>.]<列名3>
连接字段:连接谓词中的列名称
连接条件中的各连接字段类型必须是可比的,但名字不必相同
5.4.4.1 等值与非等值连接查询
连接操作的执行过程:
5.4.4.2 嵌套循环法(NESTED-LO0P
- 首先在表1中找到第一个式组,然后从头开始扫描表2,逐一查找满足连接件的元组,找到后就将表1中的第一个元组与该元组拼接起来,形成结果表中一个元组。
- 表2全部查找完后,再找表1中第二个元组,然后再从头开始扫描表2,逐一查找满足连接条件的元组,找到后就将表1中的第二个元组与该元组拼接起来,形成结果表中一个元组。重复上述操作,直到表1中的全部元组都处理完毕
5.4.4.3 自然连接
不存在重复的列
5.4.4.4 自身连接
- 自身连接:一个表与其自己进行连接
- 需要给表起别名以示区别
- 由于所有属性名都是同名属性,因此必须使用别名前缀
5.4.4.5 外连接
外连接与普通连接的区别
- 普通连接操作只输出满足连接条件的元组
- 外连接操作以指定表为连接主体,将主体表中不满足连接条件的元组一并输出
5.4.4.6 左外连接
- 列出左边关系中所有的元组
5.4.4.7 右外连接
- 列出右边关系中所有的元组
5.4.4.8 多表连接
多表连接:两个以上的表进行连接
-- [例 3. 49] 查询每个学生及其选修课程的情况
SELECT stu.sno,stu.sname,stu.ssex,sc.cno,sc.grade FROM student stu,sc WHERE stu.sno=sc.sno
-- [例 3.50]对[例 3.49]用自然连接完成。
-- [例 3.51]查询选修2号课程且成绩在90分以上的所有学生的学号和姓名。
SELECT stu.sno,stu.sname FROM student stu,sc WHERE stu.sno=sc.sno AND sc.cno='3' AND sc.grade>90
-- [例 3.52]查询每一门课的间接先修课(即先修课的先修课)
SELECT DISTINCT c2.* FROM course c1,course c2 WHERE c1.cpno=c2.cno
-- 改写[例 3. 49] 查询每个学生及其选修课程的情况,使用外连接
-- 注意:3.49是内连接,查询出来后没有未选修的学生信息。 而外连接也可以查看到未选修的学生信息
-- 同理左连接可以查看到学生的信息,则未选修的学生信息为空在右侧显示, 右连接在左侧显示
SELECT * FROM student LEFT JOIN sc ON student.sno=sc.sno
SELECT * FROM sc RIGHT JOIN student ON student.sno=sc.sno
-- [3.49]改为内连接
SELECT s.sno,s.sname,s.ssex,sc.cno,sc.grade FROM student s JOIN sc ON s.sno=sc.sno
-- [例3.54]查询每个学生的学号、姓名、选修的课程名及成绩
SELECT s.sno,s.sname,c.cname,sc.grade FROM student s,course c,sc WHERE s.sno=sc.sno AND sc.cno=c.cno
-- 使用join改造
SELECT s.sno,s.sname,c.cname,sc.grade FROM student s JOIN sc ON s.sno=sc.sno JOIN course c ON sc.cno=c.cno
5.4.5 嵌套查询
- SELECT-FROM-WHERE语句称为一个查询块
- 将一个查询块嵌套在另一个查询块的WHERE子句或HAVING短语的条件中的查询称为嵌套查询
上层的查询块称为外层查询或父查询
下层查询块称为内层查询或子香询
SQL语言允许多层嵌套查询
- 即一个子查询中还可以嵌套其他子查询
子查询的限制
- 不能使用ORDER BY子句
不相关子查询
子查询的查询条件不依赖于父查询:
- 由里向外 逐层处理。即每个子查询在上一级查询处理之前求解,子查询的结果用于建立其父查询的查找条件。
相关子查询:子查询的查询条件依赖于父查询
- 首先取外层查询中表的第一个元组,根据它与内层查询相关的属性值处理内层查询,若WHERE子句返回值为真,则取此元组放入结果表
- 然后再取外层表的下一个元组
- 重复这一过程,直至外层表全部检查完为止
5.4.5.1 带有IN谓词的子查询
-- [例 3.55] 查询与“刘晨宸”在同一个系学习的学生。
SELECT sname FROM student WHERE sdept IN (SELECT sdept FROM student WHERE sname='刘晨宸')
-- JOIN 可以替代子查询
SELECT s1.sname FROM student s1 JOIN student s2 ON s1.sdept=s2.sdept AND s2.sname='刘晨宸'
-- 用自身连接完成[例 3.55]查询要求
SELECT s1.sname FROM student s1,student s2 WHERE s1.sdept=s2.sdept AND s2.sname='刘晨宸'
-- [例 3.56]查询选修了课程名为“信息系统”的学生学号和姓名
SELECT sno,sname FROM student WHERE sno IN (SELECT sno FROM sc WHERE cno IN (SELECT cno FROM course WHERE cname='信息系统'))
-- 使用JOIN 代替
SELECT s1.sno,s1.sname FROM student s1 JOIN sc s2 ON s1.sno=s2.sno JOIN course c ON c.cno=s2.cno AND c.cname='信息系统'
-- 用自身连接
SELECT s1.sno,s1.sname FROM student s1,sc s2,course c WHERE s1.sno=s2.sno AND s2.cno=c.cno AND c.cname='信息系统'
5.4.6 带有比较运算符的子查询
当能确切知道内层查询返回单值时,可用比较运算符(>,<,=,>=,<=,!=或く>)在[例 3.55]中,由于一个学生只可能在一个系学习,则可以用 = 代替IN
-- 在[例 3.55]中,由于一个学生只可能在一个系学习,则可以用 = 代替IN
SELECT sname FROM student WHERE sdept =(SELECT sdept FROM student WHERE sname='刘晨宸')
-- 用JOIN 代替
SELECT s1.sname FROM student s1 JOIN student s2 ON s1.sdept=s2.sdept AND s2.sname='刘晨宸'
-- [例 3.57]找出每个学生超过他选修课程平均成绩的课程号。
SELECT cno FROM sc x WHERE grade > (SELECT AVG(grade) FROM sc y WHERE x.sno=y.sno)
5.4.7 带有ANY(SOME)或ALL谓词的子查询
使用ANY或ALL谓词时必须同时使用比较运算,语义为:
> ANY | 大于子查询结果中的某个值 |
> ALL | 大于子查询结果中的所有值 |
< ANY | 小于子查询结果中的某个值 |
< ALL | 小于子查询结果中的所有值 |
>= ANY | 大于等于子查询结果中的某个值 |
>= ALL | 大于等于子查询结果中的所有值 |
<= ANY | 小于等于子查询结果中的某个值 |
<= ALL | 小于等于子查询结果中的所有值 |
= ANY | 于子查询结果中的某个值 |
=ALL | 等于子查询结果中的所有值(通常没有实际意义) |
!=(或<>)ANY | 不等于子查询结果中的某个值 |
!=(或<>)ALL | 不等于子查询结果中的任何一个值 |
ANY(或SOME),ALL谓词与聚集函数、IN谓词的等价转换关系
= | <>或!= | < | <= | > | >= | |
ANY | IN | -- | <MAX | <=MAX | >MIN | >= MIN |
ALL | -- | NOT IN | <MIN | <= MIN | >MAX | >= MAX |
-- [例 3.58]查询非计算机科学系中比计算机科学系任意一个学生年龄小的学生姓名和年龄
SELECT sname,sage FROM student WHERE sdept <> 'CS' AND sage < ANY (SELECT sage FROM student WHERE sdept='CS')
-- 用聚集函数实现
SELECT MAX(sage) FROM student WHERE sdept='CS'
-- [例 3.59] 查询非计算机科学系中比计算机科学系所有学生年龄都小的学生姓名及年龄
SELECT sname,sage FROM student WHERE sdept <> 'CS' AND sage < ALL (SELECT MIN(sage) FROM student WHERE sdept='CS')
5.4.8 带有EXISTS谓词的子查询
EXISTS谓词
- 存在量词
- 带有EXISTS谓词的子查询不返回任何数据,只产生逻辑真值“true”或逻辑假值“false”
- 若内层查询结果非空,则外层的WHERE子句返回真值
- 若内层查询结果为空,则外层的WHERE子句返回假值
- 由EXISTS引出的子查询,其目标列表达式通常都用*,因为带EXISTS的子查询给出列名无实际意义。
NOT EXISTS谓词
- 若内层查询结果非空,则外层的WHERE子句返回假值
- 若内层查询结果为空,则外层的WHERE子句返回真值
不同形式的查询间的替换
- 一些带EXISTS或NOT EXISTS谓词的子查询不能被其他形式的子查询等价替换
- 所有带IN谓词、比较运算符、ANY和ALL谓词的子查询都能用带EXISTS谓词的子查询等价替换
- 用EXISES/NOT EXISTS实现全称量词
- SQL语言中没有全称量词(For all)
- 可以把带有全称量词的谓词转换为等价的带有存在量词的谓词
-- [例 3.60]查询所有选修了1号课程的学生姓名
SELECT sname FROM student WHERE EXISTS (SELECT sno FROM sc WHERE student.sno=sc.sno AND sc.cno=1)
-- [例 3.61]查询没有选修1号课程的学生姓名。
SELECT sname FROM student WHERE NOT EXISTS (SELECT sno FROM sc WHERE student.sno=sc.sno AND sc.cno=1)
-- [例 3.55]查询与“刘晨宸"在同一个系学习的学生
SELECT * FROM student s1 WHERE EXISTS (SELECT * FROM student s2 WHERE s1.sdept=s2.sdept AND s2.sname='刘晨宸')
-- [例 3.62]查询选修了全部课程的学生姓名
SELECT
5.4.9 集合查询
集合操作的种类
- 并操作UNI0N
- 交操作INTERSECT
- 差操作MINUS
参加集合操作的各查询结果的列数必须相同;对应项的数据类型也必须相同
-- [例 3.64] 查询计算机科学系的学生及年龄不大于19岁的学生
-- UNION ALL 不会去重
-- UNION 必须是同一张表的查询
SELECT * FROM student WHERE sdept = 'CS' UNION SELECT * FROM student WHERE sage <= 19
-- [例 3.65]查询选修了课程1或者选修了课程2的学生。
SELECT * FROM sc WHERE sc.cno='1' UNION SELECT * FROM sc WHERE sc.cno='2'
-- [例3.66]查询计算机科学系的学生与年龄不大于19岁的学生的交集。
SELECT * FROM student WHERE sdept='CS' INTERSECT SELECT * FROM student WHERE sage <= 19
-- 实际上就是查询计算机科学系中年龄不大于19岁的学生。
SELECT * FROM student WHERE sdept ='CS' AND sage <= 19
-- [例 3.67]查询既选修了课程1又选修了课程2的学生。
SELECT * FROM sc WHERE cno='1' INTERSECT SELECT * FROM sc WHERE cno='2'
-- [例 3.67]查询既选修了课程1又选修了课程2的学生。
SELECT sno FROM sc WHERE cno='1' AND sno IN (SELECT sno FROM sc WHERE cno='2')
--[例 3.68]查询计算机科学系的学生与年龄不大于19岁的学生的差集。
SELECT * FROM student WHERE sdept='CS' MINUS SELECT * FROM student WHERE sage <=19
5.4.10 基于派生表的查询
- 子查询不仅可以出现在WHERE子句中,还可以出现在FROM子句中,这时子查询生成的临时派生表(Derived Table)成为主查询的查询对象
- 如果子查询中没有聚集函数,派生表可以不指定属性列,子查询SELECT子句后面的列名为其缺省属性。
-- [例3.57]找出每个学生超过他自己选修课程平均成绩的课程号
SELECT sc.sno,sc.cno FROM sc,(SELECT sno,avg(grade) AS avggrade FROM sc GROUP BY sno) savg WHERE sc.sno=savg.sno AND sc.grade >= savg.avggrade
-- [例3.60]查询所有选修了1号课程的学生姓名
SELECT sname FROM student,(SELECT sno FROM sc WHERE cno='1' GROUP BY sno) sc1 WHERE student.sno=sc1.sno
5.5 数据更新
5.5.1 插入数据
两种插入数据方式:
- 插入元组
- 插入子查询结果
5.5.1.1 插入元组
语句格式:
INSERT INTQ<表名>[(<属性列1>[,<属性列2 >…)]VALUES(<常量1>[,<常量2>]… );
功能:将新元组插入指定表中
INT0子句
- 指定要插入数据的表名及属性列
- 属性列的顺序可与表定义中的顺序不一致
- 没有指定属性列:表示要插入的是一条完整的元组,且属性列属性与表定义中的顺序一致
- 指定部分属性列:插入的元组在其余属性列上取空值
VALUES子句
提供的值必须与INT0子句匹配值的个数值的类型
-- [例3.69]将一个新学生元组(学号:201215128;姓名:陈冬;性别:男;所在系:IS;年龄:18岁)插入到Student表中。
INSERT INTO student (sno,sname,ssex,sage,sdept) VALUES ('201215128','陈冬','m',18,'IS')
INSERT INTO student VALUES('201215129','马东','m',18,'IS',NULL)
-- [例3.70]将学生张成民的信息插入到Student表中,
INSERT INTO student(sno,sname,ssex,sage,sdept) VALUES('201215130','男','m',20,'CS')
-- [例3.71]插入一条选课记录('200215128','1')。
INSERT INTO sc(sno,cno) VALUES ('201215128','1')
5.5.1.2 插入子查询结果
语句格式
INSERT
INTO<表名> [(<属性列1>[,<属性列2>… )]子查询;
INTO子句
子查询
SELECT子句目标列必须与INT0子句匹配值的个数
值的类型
-- [例3.72]对每一个系,求学生的平均年龄,并把结果存入数据库
CREATE TABLE dept_age(sdept char(25),avg_age SMALLINT)
INSERT INTO dept_age(sdept,avg_age) SELECT sdept,avg(sage) FROM student GROUP BY sdept
5.5.2 修改数据
语句格式
UPDATE <表名>
SET <列名>=<表达式>[,<列名>=<表达式>]…[WHERE<条件>]:
功能
- 修改指定表中满足WHERE子句条件的元组
- SET子旬给出<表达式>的值用于取代相应的属性列
- 如果省略WHERE子句,表示要修改表中的所有元组
三种修改方式
- 修改某一个元组的值
- 修改多个元组的值
- 带子查询的修改语句
5.5.2.1 带子查询的修改语句
关系数据库管理系统在执行修改语句时会检查修改操作是否破坏表上已定义的完整性规则
- 实体完整性
- 主码不允许修改
- 用户定义的完整性:
NOT NULL约束
UNIQUE约束
值域约束
5.6 删除数据
语句格式
DELETE
<表名>FROM
功能:删除指定表中满足WHERE子句条件的元组
WHERE子句
- 指定要删除的元组
- 缺省表示要删除表中的全部元组,表的定义仍在字典中
三种删除方式
- 删除某一个元组的值
- 删除多个元组的值
- 带子查询的删除语句
-- [例3.76]删除学号为201215128的学生记录。
DELETE FROM student WHERE sno='201215128'
-- [例3.77]删除所有的学生选课记录。
DELETE FROM sc
-- [例3.78]删除计算机科学系所有学生的选课记录
DELETE FROM sc WHERE sno IN (SELECT sno FROM student WHERE sdept='CS')
5.7 空值的处理
空值就是“不知道”或“不存在“或”无意义”的值
一般有以下几种情况:
- 该属性应该有一个值,但目前不知道它的具体值
- 该属性不应该有值
- 由于某种原因不便于填写
5.7.1 空值的产生
空值是一个很特殊的值,含有不确定性。对关系运算带来特殊的问题,需要做特殊的处理。
-- [例 3.79]向SC表中插入一个元组,学生号是”201215125”,课程号是”1”,成绩为空。
INSERT INTO sc (sno,cno,grade) VALUES ('201215125','1',NULL)
-- [例3.80]将Student表中学生号为”201215138”的学生所属的系改为空值
UPDATE student SET sdept=NULL WHERE sno='201215138'
5.7.2 空值的判断
判断一个属性的值是否为空值,用IS NULL或ISNOT NULL来表示。
-- [例 3.81] 从Student表中找出漏填了数据的学生信息
SELECT * FROM student WHERE sname IS NULL OR ssex IS NULL OR sage IS NULL OR sdept IS NULL
5.7.3 空值的约束条件
属性定义(或者域定义)中
- 有NOT NULL约束条件的不能取空值
- 加了UNIQUE限制的属性不能取空值
- 码属性不能取空值
5.7.4 空值的算术运算、比较运算和逻辑运算
- 空值与另一个值(包括另一个空值)的算术运算的结果为空值
- 空值与另一个值(包括另一个空值)的比较运算的结果为UNKNOWN。
- 有UNKNOWN后,传统二值(TRUE,FALSE)逻辑就扩展成了三值逻辑
-- [例3.82]找出选修1号课程的不及格的学生(空值并不会被查出来)
SELECT * FROM sc WHERE grade < 60 AND cno='1'
-- [例 3.83]选出选修1号课程的不及格的学生以及缺考的学生,
SELECT sno FROM sc WHERE grade < 60 AND cno='1' UNION SELECT sno FROM sc WHERE grade IS NULL AND cno='1'
5.8 小结
- SQL可以分为数据定义、数据查询、数据更新、数据控制四大部分
- SQL是关系数据库语言的工业标准。大部分数据库管理系统产品都能支持SQL92,但是许多数据库系统只支持SQL99、SQL2008和SQL2011的部分特征,至今尚没有一个数据库系统能够完全支持SQL99以上的标准
六、Oracle常用函数
字符类函数CHR()实现整型转字符。dual是0racle系统内部提供的用于实现临时数据计算的特殊表。
- select chr(90),chr(72)from dual
字符串连接函数CONCAT(s1,s2)
- select concat( 'hello’,’world’)information from dual;
数字类函数cell()返回指定小数的整数
- select cell(7.3)from dual:
日期和时间类函数
- selectsysdate as系统日期from dual;--返回系统当前日期
- select add months(sysdate,1)from dual;-- 返回日期加上指定的月
-- 根据ASCII码值转换为对应的字符
SELECT CHR(90),CHR(72) FROM dual
-- 连接函数
SELECT CONCAT('hello','world') information FROM dual;
-- 数字函数
-- 向上取整
SELECT CEIL(7.3) FROM dual
-- 日期函数
SELECT SYSDATE AS 系统日期 FROM dual
-- 加2个月
SELECT ADD_MONTHS(SYSDATE,2) FROM dual
七、PL/SQL编程
7.1 概述
- PL/SQL(Procedural Language/SQL)是Oracle在数据库中引入的一种过程化编程语言。PL/SQL构建于SQL之上,可以用来编写包含SQL语句的程序。
- PL/SQL中可以通过IF语句或L00P语句控制程序的执行流程,甚至可以定义变量,在语句之间传递数据信息,从而控制程序处理的细节过程
- 因此能将SQL语句的数据操纵能力、数据查询能力和PL/SQL的过程处理能力结合在一起,达到取长补短的目的。
7.2 SQL和PL/SQL的区别
程序块
7.3 PL/SQL基本语法
合法字符:
- 所有的大写和小写英文字母
- 数字0-9
- 基本符号()+-*/く>=!
其他符号:
- 赋值:=
- a:=a+1
- 并置
- full_name := 'Narth’'Yebba’--与concat函数效果相同
7.3.1 变量
变量是指其值在程序运行过程中可以改变的数据存储结构,定义变量必须的元素就是变量名和数据类型,另外还有可选择的初始值,其标准语法格式如下:
变量名 数据类型[长度:=初始值]
DECLARE
--var_countryname VARCHAR2(50);
v_a NUMBER:=100;
v_b NUMBER;
BEGIN
v_B:=30;
-- var_countryname:='China';
-- dbms_output.put_line('Country Name is:'||var_countryname);
dbms_output.put_line('The Result is:'||(v_a+v_B));
END;
7.3.2 常量
常量是指其值在程序运行过程中不可改变的数据存储结构,定义常量必须的元素包括常量名、数据类型常量值和constant关键字,语法格式如下:
- 常量名constant 数据类型:=常量值
变量初始化
PL/SQL中未初始化的变量的初始化值是null
7.3.3基本数据类型
7.3.3.1 数值类型
- 数值类型包括NUMBER、PLSINTEGER和BINARYINTEGER
- NUMBER类型可以存储整数或浮点数,而其他两种类型智能存放整数。
- NUMBER(m,n)其中m表示总的位数,n表示小数位数。
7.3.3.2 字符类型
字符类型主要包括VARCHAR2、CHAR、LONG、NCHAR和NVARCHAR2等。这些类型的变量用来存储字符串或字符数据。
7.3.3.3 日期类型
日期类型只有DATE类型。存储日期和时间。DATE使用一个字节存储世纪、年、月、天、小时、分钟和秒
7.3.3.4 布尔类型
布尔类型只有B00LEAN,用于程序的流程控制和业务逻辑判断,其变量值可以是TRUE、FALSE和NULL中的一种。
7.3.4 特殊数据类型
7.3.4.1 %TYPE类型
使用%TYPE关键字可以声明一个与指定列名称相同的数据类型,它通常紧跟在指定列名的后面
DECLARE
var_name student.sname%TYPE;
var_sdept student.sdept%TYPE;
BEGIN
SELECT sname,sdept INTO var_name,var_sdept FROM student WHERE sno='201215123';
dbms_output.put_line('The Result is:'||var_name||',sdept:'||var_sdept);
END;
7.3.4.2 RECORD类型
记录类型就好像是一个封装了多个属性的类,也就是一个变量里包含其他变量的结构体。在记录类型的定义结构中包含成员变量及其数据类型
-- 变量类型
DECLARE
TYPE stu_type IS RECORD(
var_name student.sname%TYPE,
var_sdept student.sdept%TYPE
);
stuinfo stu_type;
BEGIN
SELECT sname,sdept INTO stuinfo FROM student WHERE sno='201215123';
dbms_output.put_line('The Result is:'||stuinfo.var_name||',sdept:'||stuinfo.var_sdept);
END;
7.3.4.3 %ROWTYPE类型
%ROWTYPE类型的变量结合了%TYPE类型和记录类型变量的优点,根据数据表中行的结构定义一种特殊的数据类型,来存储从数据表中检索到的一行数据
-- %ROWTYPE类型
DECLARE
rowvar_stu student%ROWTYPE;
BEGIN
SELECT * INTO rowvar_stu FROM student WHERE sno='201215123';
dbms_output.put_line('The Result is:'||rowvar_stu.sname||',sdept:'||rowvar_stu.sdept||',sage:'||rowvar_sage);
END;
7.3.5异常处理
-- 异常处理
-- 假设输入a=10 b=10
DECLARE
a INT;
b INT;
c NUMBER;
BEGIN
dbms_output.put_line('please input a value for a:');
-- a:=&a; -->是输入一个数
a:=&a;
dbms_output.put_line('please input a value for b:');
b:=&b;
c:=(a+b)/(a-b);
dbms_output.put_line(c);
EXCEPTION
WHEN zero_divide THEN
dbms_output.put_line('Divisor can not be zero');
END;
7.3.6 选择语句
if-then语句:
if<condition_expression> thenplsql_sentence;end if;
-- 选择语句
DECLARE
v_name1 VARCHAR2(30);
v_name2 VARCHAR2(30);
BEGIN
/* v_name1:='oracle';
v_name2:='oracle123';*/
v_name1:='oracle123';
v_name2:='oracle';
IF LENGTH(v_name1)<LENGTH(v_name2) THEN
dbms_output.put_line(v_name2||' is longer than '||v_name1);
ELSE
dbms_output.put_line(v_name2||' is shortter than '||v_name1);
END IF;
END;
-- IF-THEN-ELSEIF-ENDIF
DECLARE
v_grade NUMBER;
BEGIN
dbms_output.put_line('please input a value for graede');
v_grade:=&grade;
IF v_grade<60 THEN
dbms_output.put_line('fail');
ELSIF v_grade<70 THEN
dbms_output.put_line('qualified');
ELSIF v_grade<90 THEN
dbms_output.put_line('good');
ELSIF v_grade<100 THEN
dbms_output.put_line('excellent');
ELSE
dbms_output.put_line('perfect');
END IF;
END;
7.3.7 循环语句
7.3.7.1 loop语句
loop
循环执行的语句块;
exit when 循环结束条件;
循环结束条件修改;
end loop;
-- loop语句
DECLARE
sum_i INT:=0;
i INT:=0;
BEGIN
LOOP
i:=i+1;
sum_i:=sum_i+i;
EXIT WHEN i=100;
END LOOP;
dbms_output.put_line('one to onehunder sum='||sum_i);
END;
7.3.7.2 while...loop语句
whie(循环结束条件)loop
循环执行的语句块;
循环结束条件修改
end loop;
-- while...loop语句
DECLARE
sum_i INT:=0;
i INT:=0;
BEGIN
WHILE i<100 LOOP
i:=i+1;
sum_i:=sum_i+i;
END LOOP;
dbms_output.put_line('one to onehunder sum='||sum_i);
END;
7.3.7.3 for语句
for variable counter name in [reverse]lower_limit..upper_limit loop
plsql_sentence;
end loop;
-- for语句
DECLARE
sum_i INT:=0;
i INT:=0;
BEGIN
-- 1..100 -> >=1&&<=100 (包含100)
FOR i IN 1..100 LOOP
sum_i:=sum_i+i;
END LOOP;
dbms_output.put_line('one to onehunder sum='||sum_i);
END;
7.3.8 选择和跳转语句
7.3.8.1 case语句
-- case语句
DECLARE
season INT;
aboutinfo VARCHAR2(30);
BEGIN
season:=&season;
CASE season
WHEN 1 THEN
aboutinfo:=season||' month:1、2、3';
WHEN 2 THEN
aboutinfo:=season||' month:4、5、6';
WHEN 3 THEN
aboutinfo:=season||' month:7、8、9';
WHEN 4 THEN
aboutinfo:=season||' month:10、11、12';
ELSE
aboutinfo:='season error';
END CASE;
dbms_output.put_line(aboutinfo);
END;
7.3.8.2 goto语句 无条件跳转
-- goto语句 无条件跳转
DECLARE
v_result INT :=1;
BEGIN
FOR i IN 1..100 LOOP
IF v_result=2 THEN
GOTO endpoint;
END IF;
END LOOP;
dbms_output.put_line(v_result);
<<endpoint>>
dbms_output.put_line('over');
END;
7.3.9 游标(类似指针)
7.3.9.1 显示游标
是由用户声明和操作的一种游标,通常用于操作查询select语句返回的结果集。使用该游标的步骤:
- 声明游标
- 打开游标
- 读取游标
- 关闭游标
-- 游标(类似指针)
-- 显示游标
DECLARE
CURSOR cur_stu IS SELECT sno,sname,sage FROM student WHERE sdept='CS';
TYPE record_stu IS RECORD
(
var_sno student.sno%TYPE,
var_sname student.sname%TYPE,
var_sage student.sage%TYPE
);
stu_row record_stu;
BEGIN
OPEN cur_stu;
FETCH cur_stu INTO stu_row;
WHILE cur_stu%FOUND LOOP
dbms_output.put_line(' id: '||stu_row.var_sno||' name: '||stu_row.var_sname||' age: '||stu_row.var_sage);
FETCH cur_stu INTO stu_row;
END LOOP;
END;
7.3.9.2 隐式游标
0racle会为执行的SQL自动创建一个隐式游标。该游标是内存中处理该语句的工作区域。隐式游标主要是处理数据操纵语句(如update、delete语句)的执行结果,在使用隐式游标的属性时,需要在前面加上隐式游标的默认名称SQL
-- 隐式游标
DECLARE
BEGIN
UPDATE student SET sage=sage+1 WHERE sdept='CS';
-- SQL指向上一条的sql语句,表示隐式游标
IF SQL%NOTFOUND THEN
dbms_output.put_line(' not found any student');
ELSE
-- SQL%ROWCOUNT 表示有多少行被影响
dbms_output.put_line(SQL%ROWCOUNT ||' student has changed');
END IF;
END;
7.3.10 异常
7.3.10.1 编译时异常
-- 编译时异常
DECLARE
v_vara VARCHAR2(1);
v_varb VARCHAR2(4):='Java';
BEGIN
v_vara:=v_varb;
EXCEPTION
WHEN value_error THEN
dbms_output.put_line('value_error');
END;
7.3.10.2 用户自定义时异常
-- 用户自定义异常
DECLARE
v_data NUMBER;
v_myexp EXCEPTION;
BEGIN
v_data:=&inputdata;
IF v_data>100 THEN
RAISE v_myexp;
END IF;
dbms_output.put_line(v_data);
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('my exception');
END;
7.4 存储过程和触发器
7.4.1 存储过程(包装一个数据)
把需要重复执行的内容放在存储过程中,实现代码的复用
CREATE PROCEDURE my_proc1 IS
BEGIN
INSERT INTO student(sno,sname,sage) VALUES('201215201','李四',20);
dmbs_output.put_line('insert success');
END my_proc1;
BEGIN
my_proc1;
END;
-- 可替换追加的存储过程
CREATE OR REPLACE PROCEDURE my_proc1 IS
BEGIN
INSERT INTO student(sno,sname,sage) VALUES('201215202','王五',21);
dbms_output.put_line('insert success');
END my_proc1;
BEGIN
my_proc1;
END;
-- 删除存储过程
DROP PROCEDURE my_proc1;
7.4.2 函数
函数一般用于计算或表示某种功能,函数可以接收参数,有的函数也可以没有参数。但是函数必须要有返回值。
-- 函数
--创建函数
CREATE OR REPLACE FUNCTION get_avg_age(param_sdept VARCHAR2)RETURN NUMBER IS avg_age_result NUMBER;
BEGIN
SELECT AVG(sage) INTO avg_age_result FROM student WHERE TRIM(sdept)=param_sdept;
RETURN(ROUND(avg_age_result,2));
EXCEPTION
WHEN no_data_found THEN
dbms_output.put_line('sdept not found');
RETURN(0);
END;
DECLARE
avg_age NUMBER;
BEGIN
avg_age:=get_avg_age('CS');
dbms_output.put_line(avg_age);
END;
7.4.3 触发器(包装一个方法执行之前之后的数据)
触发器(trigger)是SQL server 提供给程序员和数据分析员来保证数据完整性的一种方法,它是与表事件相关的特殊的存储过程,它的执行不是由程序调用,也不是手工启动,而是由事件来触发比如当对一个表进行操作(insert,delete, update)时就会激活它执行。触发器经常用于加强数据的完整性约束和业务规则等。触发器可以从DBATRIGGERS,USER TRIGGERS 数据字典中查到。SQL3的触发器是一个能由系统自动执行对数据库修改的语句。
触发器的分类:
- 语句级触发器:针对一条DML语句而引起的触发器执行。无论数据操作影响多少行,触发器都只会执行一次。
- 替换触发器:定义在视图上的触发器,当用户操作视图时执行替换触发器,实现对基表的操作。
- 系统事件触发器 :DDL:create、alter、drop等发生DDL语言时,会触发系统事件触发器。除此之外还能在系统服务器的启动、关闭、出错时也会触发特定的系统事件触发器。
7.4.3.1 语句触发器
语句级触发器:针对一条DML语句而引起的触发器执行。无论数据操作影响多少行,触发器都只会执行一次。
-- 创建一个触发器
CREATE OR REPLACE TRIGGER tri_student BEFORE INSERT OR UPDATE OR DELETE ON student
DECLARE
var_tag VARCHAR2(10);
BEGIN
IF inserting THEN
var_tag:='insert';
ELSIF updating THEN
var_tag:='upadte';
ELSIF deleting THEN
var_tag:='delete';
END IF;
INSERT INTO student_log VALUES(var_tag,SYSDATE);
END tri_student;
-- 往student表里面数据操作,调用触发器
INSERT INTO student(sno,sname,sage) VALUES('202315201','wangwu',20);
UPDATE student SET sage=sage+1 WHERE sno='202315201'
DELETE FROM student WHERE sno='202315201'
-- 查询学生日志表
SELECT * FROM student_log
7.4.3.2 替换触发器
替换触发器:定义在视图上的触发器,当用户操作视图时执行替换触发器实现对基表的操作。
触发语句 | :old.字段 | :new.字段 |
---|---|---|
insert | 操作前该值不存在 | insert结束后,新增的数据值 |
update | 更新操作前的原始值 | 更新操作后的新值 |
delete | 删除操作前的原始值 | 删除后该值不存在 |
-- 替换触发器
-- 创建要给学生视图 方便从查看数据,并在视图里添加指定数据的操作
CREATE VIEW view_student_sc
AS SELECT s.sno,s.sname,sc.cno,sc.grade FROM student s,sc WHERE s.sno=sc.sno;
-- 一般情况是无法插入的,需要借助替换触发器来执行操作
INSERT INTO view_student_sc VALUES('202315202','赵六','1',100);
SELECT * FROM view_student_sc;
-- 创建一个替换触发器
CREATE OR REPLACE TRIGGER tri_insert_view
INSTEAD OF INSERT ON VIEW_student_sc FOR EACH ROW
BEGIN
INSERT INTO student(sno,sname) VALUES(:new.sno,:new.sname);
INSERT INTO sc(sno,cno,grade) VALUES (:new.sno,:new.cno,:new.grade);
END tri_insert_view;
7.5 程序包(聚宝盆)
程序包的包头:包头即为“规范”,用来规定程序包中使用哪些变量、函数、存储过程等
-- 程序包
--创建一个程序包头
CREATE OR REPLACE PACKAGE pack_student IS
FUNCTION fun_avg_sage(num_sdept VARCHAR2) RETURN NUMBER;
PROCEDURE pro_regulage_sage(num_sdept VARCHAR2);
END pack_student;
-- 创建一个程序包的主体
CREATE PACKAGE BODY pack_student IS
FUNCTION fun_avg_sage(num_sdept VARCHAR2) RETURN NUMBER IS
num_avg_sage NUMBER;
BEGIN
SELECT AVG(sage) INTO num_avg_sage FROM student WHERE TRIM(sdept)=num_sdept;
RETURN(num_avg_sage);
EXCEPTION
WHEN no_data_found THEN
dbms_output.put_line('no this sdept');
RETURN 0;
END fun_avg_sgae;
PROCEDURE pro_regulage_sage(num_sdept VARCHAR2) IS
BEGIN
UPDATE student SET sage=sage+1 WHERE TRIM(sdept)=num_sdept;
END pro_regulage_sage;
END pack_student;
7.6 索引(跟目录一样,找对应数据的地址)
在关系数据库中,索引是一种单独的、物理的对数据库表中一列或多列的值进行排序的一种存储结构,它是某个表中一列或若干列值的集合和相应的指向表中物理标识这些值的数据页的逻辑指针清单。索引的作用相当于图书的目录,可以根据目录中的页码快速找到所需的内容。
-- 索引
-- 创建一个索引
SELECT * FROM student WHERE sname LIKE '赵六';
CREATE INDEX idx_sname ON student(sname);
DROP INDEX idx_sname;
7.7 用户管理与权限分配
Oracle的安全保护流程
- 用户向数据库提供身份识别信息
- 输入密码
- 验证密码是否正确
7.7.1 用户与模式
模式:用户拥有的对象的集合。
创建用户
create user user_name identified by pass_word -- 创建时可以指明默认表空间和临时表空间
-- 用户管理与权限分配
-- 创建用户
CREATE USER oracleedu IDENTIFIED BY 123
DEFAULT TABLESPACE USERS
TEMPORARY TABLESPACE temp;
-- 修改用户在表空间上的磁盘上限:
ALTER USER oracleedu QUOTA 20m ON USERS;
-- 修改用户密码
ALTER USER oracleedu IDENTIFIED BY 123123;
-- 解锁被锁定的用户
ALTER USER oracleedu ACCOUNT UNLOCK;
-- 删除用户
DROP USER oracleedu[CASCADE] --cascade,一并删除用户拥有的对象
创建用户后用户不能操作数据库的,只有拥有相应的权限才能操作。
- 系统权限:
系统权限是在系统级对数据库进行存取和使用的机制,比如,用户是否能够连接到数据库系统执行系统级的DDL语句等。
- 对象权限:
对象权限是指某一个用户对其他用户的表、视图、序列、存储过程、函数、包等的操作权限。不同类型的对象具有不同的对象权限。
授权操作
授权操作:授予用户系统权限
grant cconnect to 用户名[with admin option]--把连接权限给qfedu用户 with admin option可将权限授予其他人
回收系统权限
revoke connect from 用户名;
对象授权
grant select,insert,delete,update on scott.student to 用户名;
回收对象权限
revoke delete,update on scott.student from 用户名;
-- 授予权限
GRANT CONNECT TO orcleedu;
-- 回收系统权限
REVOKE CONNECT FROM orcleedu;
-- 授予对象权限,可以在当前账户下操作其他账户中的表的数据
GRANT SELECT,insert,DELETE,UPDATE ON scott.student TO oracleedu;
-- 回收对象权限
REVOKE SELECT,INSERT,UPDATE ON scott.student FROM oracleedu;
7.7.2 角色管理
什么是角色
角色是一个独立的数据库实体,它包括一组权限。
角色包括一个或者多个权限的集合。
-- 角色管理
-- 创建角色
CREATE ROLE oraclehr IDENTIFIED BY 123;
-- 给角色授予权限
GRANT CREATE VIEW,CREATE TABLE TO oraclehr;
-- 把角色授予用户
GRANT oraclehr TO oracleedu;
-- 查询当前角色的权限
-- role_sys_privs是存放角色权限的数据字典
SELECT * FROM role_sys_privs WHERE ROLE='oracler';
-- 删除角色
DROP ROLE oraclehr;
7.7.3 使用profile管理密码
建立profile文件:create profile password life time limit password life time 30password grace time 30;
使用profile能够实现:
- 账户锁定: 连续两次输错密码
- 账户锁定时间: 30天警告,第33天oracle强制用户修改密码
- 密码历史:密码的可重复次数和可重用时间
- 密码的复杂程度:强制密码具有一定的复杂度,比如不能和用户名相同
profile还可以管理用户资源
- 一次会话使用的cpu时间
- 用户的并发会话数
- 会话总计连接时间
7.8 事务
7.8.1 事务的特性
- 原子性 Atomicity
- 一致性 Consistency
- 隔离性 Isolation
- 持久性 Durability
提交事务
在执行提交操作之前,操作的数据并不会持久保存到数据库中。
事务的提交方式有三种:
- 显示提交:使用commit命令使当前事务立即生效。
- 自动提交:执行”setautocommiton“命令
- 隐式提交:如果发生DDL命令、程序中断或关闭会话、关闭数据库等操作,则会也会完成一次事务提交。
回滚事务
回滚事务(rollback操作)。在执行提交操作之前,oracle会在重做日志中记录数据所做的修改。通过事务回滚操作,让数据恢复到修改之前的状态。事务回滚需要经过以下过程:
- 使用回退段中的数据,撤销对数据库所做的修改
- Oracle释放事务所使用的系统资源
- 通知用户事务回退成功
事务回退点
- 设置回退点:savepoint sp1;
- 回滚到回退点:rollback to sp1;
-- 事务
INSERT INTO student(sno,sname) VALUES('202422233','小明');
SELECT * FROM student;
-- 提交事务,在执行提交操作之前,操作的数据并不会持久保存到数据库中, 否则在新的sql窗口中执行操作将会查不到插入的数据
COMMIT;
-- 事务回退点
SELECT * FROM student;
UPDATE student SET sname='xiaohong' WHERE sno='20222010';
SAVEPOINT s2;
UPDATE student SET sname='xiaohua' WHERE sno='20222011';
ROLLBACK TO s2;
COMMIT;
7.9 锁机制
oracle有两种锁机制:
- 共享锁:通过数据存取的高并行性来实现。如果获得一个共享锁,用户就可以共享相同的资源。共享锁使用在读取数据的维度。
- 独占锁。防止共同改变相同的资源。如果一个事务获得一个独占锁。那么只能当前事务进行修改数据。其他不能修改数据,但可以读取数据。
死锁
- 当两个或多个用户等待其中一个被锁住的资源时,就有可能发生死锁现象。
- oracle会自动进行定期搜索,通过回滚死锁中造成死锁的一个语句来解决死锁。
- 用户在设计应用程序时要尽量避免死锁。