Web-第二十四天 Oracle学习【悟空教程】

Web-第二十四天 Oracle学习【悟空教程】_数据


Oracle应用开发实战

一、Oracle的基本概念和安装

l Oracle简介

ORACLE数据库系统是美国ORACLE公司(甲骨文)提供的以分布式数据库为核心的一组软件产品,是目前最流行的客户/服务器(CLIENT/SERVER)或B/S体系结构的数据库之一。比如SilverStream就是基于数据库的一种中间件。ORACLE数据库是目前世界上使用最为广泛的数据库管理系统,作为一个通用的数据库系统,它具有完整的数据管理功能;作为一个关系数据库,它是一个完备关系的产品;作为分布式数据库它实现了分布式处理功能。但它的所有知识,只要在一种机型上学习了ORACLE知识,便能在各种类型的机器上使用它。


l Oracle10g的安装

1. 解压oracle数据库安装包,如果是win7或者win8系统右键点击setup.exe选择兼容性,以xp方式,并且以管理员方式运行,以及其他所有用户都按着此规则如图

Web-第二十四天 Oracle学习【悟空教程】_数据_02 

Web-第二十四天 Oracle学习【悟空教程】_数据_03


2. 如果是xp系统可以直接并双击解压目录下的setup.exe,出现安装界面,如下:

Web-第二十四天 Oracle学习【悟空教程】_oracle_04 

3. 输入口令和确认口令,如:javahelp,点击下一步,出现如下进度条,

注:此口令即是管理员密码。

Web-第二十四天 Oracle学习【悟空教程】_数据_05


4. 检查先决条件,选中红框所示的选择框,如下图:

Web-第二十四天 Oracle学习【悟空教程】_sql_06 

5. 点击“下一步”,出现“概要”界面,点击“安装”。

Web-第二十四天 Oracle学习【悟空教程】_oracle_07


6. 出现安装进度条,等待安装完成,如下图:

Web-第二十四天 Oracle学习【悟空教程】_数据_08


7. 安装完成后,自动运行配置向导,如下图,等待其完成:

Web-第二十四天 Oracle学习【悟空教程】_oracle_09


8. 完成后,出现“口令管理”界面,点击“口令管理”,如下图:

Web-第二十四天 Oracle学习【悟空教程】_sql_10 

9. 将SCOTT和HR用户的沟去掉(解锁这两个账户),如下图所示,点击“确定”:

Web-第二十四天 Oracle学习【悟空教程】_oracle_11 

10. 回到“口令管理”界面,点击“确定”,如下图:

Web-第二十四天 Oracle学习【悟空教程】_sql_12


11. 安装结束,点击“退出”。

Web-第二十四天 Oracle学习【悟空教程】_数据_13


l 虚拟网卡设置

本机和虚拟机之间能相互访问,它们的IP段必须相同,但是本机将会连接不同的网络环境(比如教室、宿舍、家庭),那么本机的IP段会产生变化就连不上虚拟机了,为了避免这种情况我们让本机和虚拟机之间用虚拟网卡的方式互相通信,配置方式参考如下文档:

Web-第二十四天 Oracle学习【悟空教程】_oracle_14 

l PLSQL Developer客户端工具的安装

1. 网络的测试

参考:

Web-第二十四天 Oracle学习【悟空教程】_sql_15 

2. 安装PLSQL Developer客户端

Web-第二十四天 Oracle学习【悟空教程】_数据_16 

3. 中文乱码的处理

Web-第二十四天 Oracle学习【悟空教程】_sql_17 

二、Oracle数据库的体系结构

l 数据库:database

Oracle数据库是数据的物理存储。这就包括(数据文件ORA或者DBF、控制文件、联机日志、参数文件)。其实Oracle数据库的概念和其它数据库不一样,这里的数据库是一个操作系统只有一个库。可以看作是Oracle就只有一个大数据库。


l 实例:  

一个Oracle实例(Oracle Instance)有一系列的后台进程(Backguound Processes)和内存结构(Memory Structures)组成。一个数据库可以有n个实例。


l 数据文件(dbf):

数据文件是数据库的物理存储单位。数据库的数据是存储在表空间中的,真正是在某一个或者多个数据文件中。而一个表空间可以由一个或多个数据文件组成,一个数据文件只能属于一个表空间。一旦数据文件被加入到某个表空间后,就不能删除这个文件,如果要删除某个数据文件,只能删除其所属于的表空间才行。


l 表空间:

表空间是Oracle对物理数据库上相关数据文件(ORA或者DBF文件)的逻辑映射。一个数据库在逻辑上被划分成一到若干个表空间,每个表空间包含了在逻辑上相关联的一组结构。每个数据库至少有一个表空间(称之为system表空间)。

每个表空间由同一磁盘上的一个或多个文件组成,这些文件叫数据文件(datafile)。一个数据文件只能属于一个表空间。

Web-第二十四天 Oracle学习【悟空教程】_数据_18 

l 用户:

用户是在实例下建立的。不同实例中可以建相同名字的用户。

注: 表的数据,是有用户放入某一个表空间的,而这个表空间会随机把这些表数据放到一个或者多个数据文件中。


由于oracle的数据库不是普通的概念,oracle是有用户和表空间对数据进行管理和存放的。但是表不是有表空间去查询的,而是由用户去查的。因为不同用户可以在同一个表空间建立同一个名字的表!这里区分就是用户了!

Web-第二十四天 Oracle学习【悟空教程】_sql_19


l SCOTT用户和HR用户

Oracle为了让学习者更好的进行学习,在安装成功后,也创建了初始的用户,其中SCOTT与HR就是初始的普通用户。这些用户下面都默认存在了表结构,我们重点掌握SCOTT用户下的所有表,如下所示:

SCOTT用户下的表

Web-第二十四天 Oracle学习【悟空教程】_数据_20


HR用户下的表

Web-第二十四天 Oracle学习【悟空教程】_sql_21


三、基本查询

l 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控制对表单个列的访问。


l Select语句的语法格式和示例

Web-第二十四天 Oracle学习【悟空教程】_数据_22 

1. 查询语法

Select * |列名 from 表名

Web-第二十四天 Oracle学习【悟空教程】_oracle_23 

Web-第二十四天 Oracle学习【悟空教程】_数据_24


2.别名用法

在查询的结果列中可以使用别名

Select  列名 别名,列名别名,... from emp;

别名中,有没有双引号的区别就在于别名中有没有特殊的符号或者关键字。

Web-第二十四天 Oracle学习【悟空教程】_oracle_25


3.消除重复的数据

Select distinct *|列名, ... from emp;

Web-第二十四天 Oracle学习【悟空教程】_数据_26 

使用distinct可以消除重复的行,如果查询多列的必须保证多列都重复才能去掉重复


4. 查询中四则运算

查询每个雇员的年薪

select ename, sal*12 from emp;

select ename, sal*12 income from emp;

Web-第二十四天 Oracle学习【悟空教程】_oracle_27 

Sql中支持四则运算“+,-,*,/”


l 什么是空值?

  • 空值是无效的,未指定的,未知的或不可预知的值

  • 空值不是空格或者0 。

注意:*、包含null的表达式都为null

      *、空值永远不等于空值


l 连接符 ||

字符串连接查询

Mysql中实现方法:

Web-第二十四天 Oracle学习【悟空教程】_数据_28


查询雇员编号,姓名,工作

编号是:7369的雇员, 姓名是:smith,工作是:clerk

Web-第二十四天 Oracle学习【悟空教程】_数据_29

字符串的连接使用‘||’


四、条件查询和排序

l 使用where语句对结果进行过滤

Web-第二十四天 Oracle学习【悟空教程】_数据_30 

l 比较运算符

Web-第二十四天 Oracle学习【悟空教程】_oracle_31 

l 其他比较运算符

Web-第二十四天 Oracle学习【悟空教程】_数据_32 

l 逻辑运算符

Web-第二十四天 Oracle学习【悟空教程】_数据_33 

l Where语句示例

1. 非空和空的限制

示例:查询每月能得到奖金的雇员

分析:只要字段中存在内容表示不为空,如果不存在内容就是null,

语法:列名 IS NOT NULL

为空  列名 IS NULL

Web-第二十四天 Oracle学习【悟空教程】_oracle_34 

Web-第二十四天 Oracle学习【悟空教程】_数据_35 

范例:查询工资大于1500并且有奖金领取的雇员

分析:多个查询条件同时满足之间使用‘AND’

Web-第二十四天 Oracle学习【悟空教程】_oracle_36 

范例:查询工资大于1500或者有奖金的雇员

分析:多个查询条件或满足,条件之间使用“OR”

Web-第二十四天 Oracle学习【悟空教程】_数据_37 

范例:查询工资不大于1500和没有奖金的人

语法:NOT(查询条件)

Web-第二十四天 Oracle学习【悟空教程】_数据_38 

2.范围限制

范例:基本工资大于1500但是小于3000的全部雇员

分析:sal>1500, sal<3000

Web-第二十四天 Oracle学习【悟空教程】_sql_39 

Between  and等于 sal > =1500 and sal <= 3000

Web-第二十四天 Oracle学习【悟空教程】_sql_40 

范例:查询1981-1-1到1981-12-31号入职的雇员

分析:between and 不仅可以使用在数值之间,也可以用在日期的区间

Web-第二十四天 Oracle学习【悟空教程】_sql_41 

范例:查询雇员名字叫smith的雇员

在oracle中的查询条件中查询条件的值是区分大小写的

Web-第二十四天 Oracle学习【悟空教程】_sql_42 

Web-第二十四天 Oracle学习【悟空教程】_数据_43 

范例:查询雇员编号是7369,7499,7521的雇员编号的具体信息

如果使用之前的做法可以使用OR关键字

Web-第二十四天 Oracle学习【悟空教程】_oracle_44 

实际上,此时指定了查询范围,那么sql可以使用IN关键字

语法: 列名 IN (值1,值2,....)

 列名 NOT IN (值1, 值2,...)

其中的值不仅可以是数值类型也可以是字符串

Web-第二十四天 Oracle学习【悟空教程】_sql_45


范例:查询雇员姓名是’SMITH’,’ALLEN’,’WARD’的雇员具体信息

Web-第二十四天 Oracle学习【悟空教程】_oracle_46 

3.模糊查询

在常用的站点中经常会有模糊查询,即:输入一个关键字,把符合的内容全部的查询出来,在sql中使用LIKE语句完成。

在LIKE中主要使用以下两种通配符

“%”:可以匹配任意长度的内容

“_”:可以匹配一个长度的内容

范例:查询出所有雇员姓名中第二个字符包含“M”的雇员

Web-第二十四天 Oracle学习【悟空教程】_oracle_47 

在LIKE中如果没有关键字表示查询全部

Web-第二十四天 Oracle学习【悟空教程】_oracle_48 

查询名字中带有“M”的雇员

Web-第二十四天 Oracle学习【悟空教程】_数据_49 

在oracle中不等号的用法可以有两种形式“<>”和“!=”

范例:查询雇员编号不是7369的雇员信息

Web-第二十四天 Oracle学习【悟空教程】_数据_50 

Web-第二十四天 Oracle学习【悟空教程】_数据_51


l 使用order by对结果排序

1.排序的语法

在sql中可以使用ORDER BY对查询结果进行排序

语法:SELECT * |列名 FROM 表名 {WEHRE 查询条件} ORDER BY 列名1 ASC|DESC,列名2...ASC|DESC

范例:查询雇员的工资从低到高

分析:ORDER BY 列名 默认的排序规则是升序排列,可以不指定ASC,如果按着降序排列必须指定DESC

Web-第二十四天 Oracle学习【悟空教程】_sql_52

Web-第二十四天 Oracle学习【悟空教程】_sql_53 

如果存在多个排序字段可以用逗号分隔

Web-第二十四天 Oracle学习【悟空教程】_oracle_54 

注意ORDER BY语句要放在sql的最后执行。


2.排序中的空值问题

当排序时有可能存在null时就会产生问题,我们可以用 nulls first ,  nulls last来指定null值显示的位置。

--查询雇员的工资从低到高

select * from emp order by sal nulls first;

select * from emp order by sal desc nulls last ;


五、单行函数

l 什么是SQL的函数?

Web-第二十四天 Oracle学习【悟空教程】_sql_55 

l 函数的类型

Web-第二十四天 Oracle学习【悟空教程】_sql_56 

l 单行函数

Web-第二十四天 Oracle学习【悟空教程】_sql_57 

字符函数

Web-第二十四天 Oracle学习【悟空教程】_oracle_58


示例:

接收字符输入返回字符或者数值,dual是伪表

1. 字符串的连接可以使用concat可以使用“||”建议使用“||”

concat('hello', 'world')

Web-第二十四天 Oracle学习【悟空教程】_sql_59 

2. 字符串的截取,使用substr,第一个参数是源字符串,第二个参数是开始索引,第三个参数长度,开始的索引使用1和0效果相同

substr('hello', 1,3)

Web-第二十四天 Oracle学习【悟空教程】_oracle_60 

3. 获取字符串的长度

length('hello')

Web-第二十四天 Oracle学习【悟空教程】_数据_61 

4. 字符串替换,第一个参数是源字符串,第二个参数被替换的字符串,第三个是替换字符串

replace('hello', 'l','x')

Web-第二十四天 Oracle学习【悟空教程】_sql_62 

数值函数

Web-第二十四天 Oracle学习【悟空教程】_sql_63 

日期函数

  • Oracle中的日期:

Oracle  中的日期型数据实际含有两个值 : 日期和时间。

默认的日期格式是  DD-MON-RR 。


  • 日期的数学运算

在日期上加上或减去一个数字结果仍为日期

两个日期相减返回日期之间相差的天数

可以用数字除24


  • 日期函数示例

1. 范例:查询雇员的进入公司的周数。

分析:查询雇员进入公司的天数(sysdate – 入职日期)/7就是周数

Web-第二十四天 Oracle学习【悟空教程】_sql_64 

2. 获得两个时间段中的月数:MONTHS_BETWEEN()

范例:查询所有雇员进入公司的月数

Web-第二十四天 Oracle学习【悟空教程】_数据_65 

3. 获得几个月后的日期:ADD_MONTHS()

范例:求出三个月后的日期

Web-第二十四天 Oracle学习【悟空教程】_sql_66 

换函数

Web-第二十四天 Oracle学习【悟空教程】_oracle_67


  • TO_CHAR 函数对日期的

Web-第二十四天 Oracle学习【悟空教程】_sql_68 

日期的格式:

Web-第二十四天 Oracle学习【悟空教程】_oracle_69 

  • TO_CHAR 函数对数字的

Web-第二十四天 Oracle学习【悟空教程】_oracle_70 

数字换的格式:

Web-第二十四天 Oracle学习【悟空教程】_sql_71 

  • TO_NUMBER和TO_DATE函数

Web-第二十四天 Oracle学习【悟空教程】_oracle_72 

Web-第二十四天 Oracle学习【悟空教程】_oracle_73


  • 示例:

1.​ ​TO_CHAR:字符串换函数

范例:查询所有的雇员将将年月日分开,此时可以使用TO_CHAR函数来拆分

拆分时需要使用通配符

年:y, 年是四位使用yyyy

月:m, 月是两位使用mm

日:d,​ ​日是两位使用dd

Web-第二十四天 Oracle学习【悟空教程】_oracle_74 

在结果中10以下的月前面被被补了前导零,可以使用fm去掉前导零

Web-第二十四天 Oracle学习【悟空教程】_sql_75 

2.​ ​TO_NUMBER:数值换函数

TO_NUMBER可以把字符串换成数值

Web-第二十四天 Oracle学习【悟空教程】_数据_76

3. TO_DATE:日期换函数

TO_DATE可以把字符串的数据换成日期类型

Web-第二十四天 Oracle学习【悟空教程】_oracle_77


通用函数

  • 什么是通用函数?

这些函数适用于任何数据类型,同时也适用于空值


  • 常用的通用函数

Web-第二十四天 Oracle学习【悟空教程】_数据_78 

  • 通用函数示例

1.空值处理nvl

范例:查询所有的雇员的年薪

Web-第二十四天 Oracle学习【悟空教程】_数据_79 

我们发现很多员工的年薪是空的,原因是很多员工的奖金是null,null和任何数值计算都是null,这时我们可以使用nvl来处理。

Web-第二十四天 Oracle学习【悟空教程】_oracle_80


条件表达式

  • 什么是条件表达式?

在 SQL语句中使用IF-THEN-ELSE


  • 实现的方式:

CASE 表达式:SQL99的语法,类似Basic,比较繁琐

DECODE 函数:Oracle自己的语法,类似Java,比较简介


  • CASE表达式

Web-第二十四天 Oracle学习【悟空教程】_sql_81 

  • DECODE 函数

Web-第二十四天 Oracle学习【悟空教程】_oracle_82 

  • 条件表达式示例: 根据10号部门员工的工资,显示税率

Web-第二十四天 Oracle学习【悟空教程】_sql_83


六、多行函数

l 什么是多行函数?

分组函数作用于一组数据,并对一组数据返回一个值。

也叫:组函数、分组函数

组函数会忽略空值;NVL 函数使分组函数无法忽略空值


l 常用的多行函数

Web-第二十四天 Oracle学习【悟空教程】_oracle_84 


l 多行函数示例

1.统计记录数count()

范例:查询出所有员工的记录数

Web-第二十四天 Oracle学习【悟空教程】_oracle_85 

不建议使用count(*),可以使用一个具体的列以免影响性能。

Web-第二十四天 Oracle学习【悟空教程】_oracle_86 


2.最小值查询min()

范例:查询出来员工最低工资

Web-第二十四天 Oracle学习【悟空教程】_sql_87 


3.最大值查询max()

范例:查询出员工的最高工资

Web-第二十四天 Oracle学习【悟空教程】_sql_88 


4.查询平均值avg()

范例:查询出员工的平均工资

Web-第二十四天 Oracle学习【悟空教程】_sql_89 


5.求和函数sum()

范例:查询出20号部门的员工的工资总和

Web-第二十四天 Oracle学习【悟空教程】_oracle_90


l  分组数据

Web-第二十四天 Oracle学习【悟空教程】_sql_91 

范例:查询每个部门的人数

Web-第二十四天 Oracle学习【悟空教程】_数据_92 

范例:查询出每个部门的平均工资

Web-第二十四天 Oracle学习【悟空教程】_oracle_93


范例:查询出来部门编号,和部门下的人数

Web-第二十四天 Oracle学习【悟空教程】_数据_94 

我们发现报了一个ORA-00937的错误

注意:

如果使用分组函数,SQL只可以把GOURP BY分组条件字段和分组函数查询出来,不能有其他字段。

如果使用分组函数,不使用GROUP BY 只可以查询出来分组函数的值

Web-第二十四天 Oracle学习【悟空教程】_oracle_95 

l 过滤分组数据

范例:查询出部门平均工资大于2000的部门

Web-第二十四天 Oracle学习【悟空教程】_oracle_96


l WHERE和HAVING的区别

最大区别在于:where后面不能有组函数

Web-第二十四天 Oracle学习【悟空教程】_数据_97


Oracle第二天

七、多表查询

l 什么是笛卡尔积?

Web-第二十四天 Oracle学习【悟空教程】_sql_98 

l Oracle的连接条件的类型

  • 等值连接

  • 不等值连接

  • 外连接

  • 自连接


l Oracle多表连接示例

1.多表连接基本查询

使用一张以上的表做查询就是多表查询

语法: SELECT {DISTINCT} *|列名.. FROM 表名 别名,表名1 别名

{WHERE 限制条件 ORDER BY 排序字段 ASC|DESC...}

范例:查询员工表和部门表

Web-第二十四天 Oracle学习【悟空教程】_sql_99 

我们发现产生的记录数是56条,我们还会发现emp表是14条,dept表是4条,56正是emp表和dept表的记录数的乘积,我们称其为笛卡尔积。

如果多张表进行一起查询而且每张表的数据很大的话笛卡尔积就会变得非常大,对性能造成影响,想要去掉笛卡尔积我们需要关联查询。

在两张表中我们发现有一个共同的字段是depno,depno就是两张表的关联的字段,我们可以使用这个字段来做限制条件,两张表的关联查询字段一般是其中一张表的主键,另一张表的外键。

Web-第二十四天 Oracle学习【悟空教程】_数据_100 

关联之后我们发现数据条数是14条,不在是56条。

多表查询我们可以为每一张表起一个别名

Web-第二十四天 Oracle学习【悟空教程】_oracle_101 

范例:查询出雇员的编号,姓名,部门的编号和名称,地址

Web-第二十四天 Oracle学习【悟空教程】_sql_102 

范例:查询出每个员工的上级领导

分析:emp表中的mgr字段是当前雇员的上级领导的编号,所以该字段对emp表产生了自身关联,可以使用mgr字段和empno来关联

Web-第二十四天 Oracle学习【悟空教程】_oracle_103 


范例:在上一个例子的基础上查询该员工的部门名称

分析:只要在上一个例子基础上再加一张表的关联,使用deptno来做关联字段即可

Web-第二十四天 Oracle学习【悟空教程】_sql_104 

范例:查询出每个员工编号,姓名,部门名称,工资等级和他的上级领导的姓名,工资等级

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

Web-第二十四天 Oracle学习【悟空教程】_数据_105 

2.外连接(左右连接)

1). 右连接

当我们在做基本连接查询的时候,查询出所有的部门下的员工,我们发现编号为40的部门下没有员工,但是要求把该部门也展示出来,我们发现上面的基本查询是办不到的

Web-第二十四天 Oracle学习【悟空教程】_oracle_106 

使用(+)表示左连接或者右连接。


范例:查询出所有员工的上级领导

分析:我们发现使用我们以前的做法发现KING的上级领导没有被展示,我们需要使用外连接把他查询出来

Web-第二十四天 Oracle学习【悟空教程】_数据_107 

如果用left join实现:

Web-第二十四天 Oracle学习【悟空教程】_数据_108

因为(+)这种形式是oracle数据库独有的,所以要求大家一定要掌握left join 或right join方式的写法。


八、子查询

l 什么是子查询?

使用子查询解决问题:谁的工资比SCOTT高?

Web-第二十四天 Oracle学习【悟空教程】_sql_109 

l 子查询的语法

Web-第二十四天 Oracle学习【悟空教程】_oracle_110

  • 子查询 (内查询) 在主查询之前一次执行完成。

  • 子查询的结果被主查询使用 (外查询)。


l 子查询的类型

Web-第二十四天 Oracle学习【悟空教程】_数据_111 

l 单行子查询

  • 只返回一条记录

  • 单行操作符

Web-第二十四天 Oracle学习【悟空教程】_oracle_112 

  • 单行子查询示例1

Web-第二十四天 Oracle学习【悟空教程】_sql_113 

  • 单行子查询示例2

Web-第二十四天 Oracle学习【悟空教程】_数据_114 

  • 单行子查询示例3

Web-第二十四天 Oracle学习【悟空教程】_sql_115 

  • 单行子查询示例4

范例:查询出比雇员7654的工资高,同时从事和7788的工作一样的员工

Web-第二十四天 Oracle学习【悟空教程】_数据_116 

范例:要求查询每个部门的最低工资和最低工资的雇员和部门名称

Web-第二十四天 Oracle学习【悟空教程】_数据_117 

  • 非法使用单行子查询示例

Web-第二十四天 Oracle学习【悟空教程】_sql_118 

l 多行子查询

  • 返回了多条记录

  • 多行操作符


l 子查询中的null值问题

  • 单行子查询中的null值问题

Web-第二十四天 Oracle学习【悟空教程】_sql_119


  • 多行子查询中的null值问题

示例:查询不是老板的员工

Web-第二十四天 Oracle学习【悟空教程】_数据_120 

多行子查询中null值需要注意的问题:

Web-第二十四天 Oracle学习【悟空教程】_数据_121 

l Exists用法:

语法解释:

exists(sql查询语句)

sql查询语句为空 返回值是false

sql查询语句有值 返回值就是true


select  * from emp where exists (select * from dept where deptno=1)

等同于:select  * from emp where 1=2


select  * from emp where exists (select * from dept where deptno=10)

等同于:select  * from emp where 1=1


范例:查询有员工的部门

select *  from dept d

 where not exists (select * from emp e where e.deptno = d.deptno)


九、课堂练习

l 找到员工表中工资最高的前三名,如下格式:

Web-第二十四天 Oracle学习【悟空教程】_oracle_122 

l 找到员工表中薪水大于本部门平均薪水的员工。

Web-第二十四天 Oracle学习【悟空教程】_sql_123 


l 统计每年入职的员工个数

Web-第二十四天 Oracle学习【悟空教程】_数据_124


l 补充知识点:Oracle中的分页查询

ROWNUM:表示行号,实际上只是一个列,但是这个列是一个伪列,此列可以在每张表中出现。

ROWID:表中每行数据指向磁盘上的物理地址。 


十、集合运算

l 什么是集合运算?

Web-第二十四天 Oracle学习【悟空教程】_oracle_125 

l 并集

Web-第二十四天 Oracle学习【悟空教程】_oracle_126    Web-第二十四天 Oracle学习【悟空教程】_sql_127

范例:工资大于1500,或者是20号部门下的员工(并集)

select * from emp where sal>1500

union  -- 或union all 

select * from emp where  deptno=20;


l 交集

Web-第二十四天 Oracle学习【悟空教程】_sql_128 

范例:工资大于1500,并且是20号部门下的员工(交集)

select * from emp where sal>1500

intersect --交集

select * from emp where  deptno=20;


l 差集

Web-第二十四天 Oracle学习【悟空教程】_sql_129

--范例:1981年入职的普通员工(不包括总裁和经理)(差集)

select * from emp where to_char(hiredate,'yyyy')='1981'

minus

select * from emp where job='PRESIDENT' or job='MANAGER'


l 集合运算的特征

集合运算两边查询的字段数量、字段类型、顺序必须一致


Oracle第三天

使用DDL语句管理表

创建表空间

表空间?  ORACLE数据库的逻辑单元。  数据库---表空间   一个表空间可以与多个数据文件(物理结构)关联一个数据库下可以建立多个表空间,一个表空间可以建立多个用户、一个用户下可以建立多个表。



create tablespace javahelp001

datafile 'c:\javahelp001.dbf'

size 100m

autoextend on

next 10m


javahelp 为表空间名称

datafile  指定表空间对应的数据文件  

size  后定义的是表空间的初始大小

autoextend on  自动增长 ,当表空间存储都占满时,自动增长

next 后指定的是一次自动增长的大小。


用户

1、创建用户


create user javahelpuser

identified by javahelp

default tablespace javahelp001


identified by  后边是用户的密码  

default tablespace 后边是表空间名称

oracle数据库与其它数据库产品的区别在于,表和其它的数据库对象都是存储在用户下的。


2、用户赋权限

新创建的用户没有任何权限,登陆后会提示

Web-第二十四天 Oracle学习【悟空教程】_oracle_130

Oracle中已存在三个重要的角色:connect角色,resource角色,dba角色。

CONNECT角色: --是授予最终用户的典型权利,最基本的

        ALTER SESSION --修改会话

        CREATE CLUSTER --建立聚簇

        CREATE DATABASE LINK --建立数据库链接

        CREATE SEQUENCE --建立序列

        CREATE SESSION --建立会话

        CREATE SYNONYM --建立同义词

        CREATE VIEW --建立视图

  RESOURCE角色: --是授予开发人员的

        CREATE CLUSTER --建立聚簇

        CREATE PROCEDURE --建立过程

        CREATE SEQUENCE --建立序列

        CREATE TABLE --建表

        CREATE TRIGGER --建立触发器

        CREATE TYPE --建立类型


DBA角色:拥有全部特权,是系统最高权限,只有DBA才可以创建数据库结构,并且系统权限也需要DBA授出,且DBA用户可以操作全体用户的任意基表,包括删除


grant dba to javahelpuser


进入system用户下给用户赋予dba权限,否则无法正常登陆


创建表

语法:

Web-第二十四天 Oracle学习【悟空教程】_数据_131


数据的类型:

Web-第二十四天 Oracle学习【悟空教程】_sql_132


使用子查询创建表的语法:

Web-第二十四天 Oracle学习【悟空教程】_oracle_133

创建表范例:创建person表

create table person(

       pid      number(10),

       name     varchar2(10),

       gender   number(1)  default 1,

       birthday date

);

insert into person(pid, name, gender, birthday)

values(1, '张三', 1, to_date('1999-12-22', 'yyyy-MM-dd'));


修改表

在sql中使用alter可以修改表

添加语法:ALTER TABLE 表名称 ADD(列名1 类型 [DEFAULT 默认值],列名1 类型 [DEFAULT 默认值]...)

修改语法:ALTER TABLE 表名称 MODIFY(列名1 类型 [DEFAULT 默认值],列名1 类型 [DEFAULT 默认值]...)

修改列名: ALTER TABLE 表名称 RENAME COLUMN 列名1 TO 列名2

范例:在person表中增加列address

alter table person add(address varchar2(10));

范例:把person表的address列的长度修改成20长度

alter table person modify(address varchar2(20));


删除表

语法:DROP TABLE 表名


约束

在数据库开发中,约束是必不可少,使用约束可以更好的保证数据的完整性。在Oracle数据库中,约束的类型包括:

主键约束(Primary Key)

非空约束(Not Null)

唯一约束(Unique)

外键约束(Foreign Key)

检查性约束(Check)


1.主键约束

主键约束都是在id上使用,而且本身已经默认了内容不能为空,可以在建表的时候指定。

创建一张表,把pid作为主键

create table person(

       pid      number(10) primary key,

       name     varchar2(10),

       gender   number(1)  default 1,

       birthday date

);

主键不可重复, SCOTT.SYS_C0017981是系统自动分配的约束的名字

Web-第二十四天 Oracle学习【悟空教程】_数据_134 

主键不可为空

Web-第二十四天 Oracle学习【悟空教程】_sql_135 

我们可以自己来指定主键约束的名字

create table person(

       pid      number(10),

       name     varchar2(10),

       gender   number(1)  default 1,

       birthday date,

       constraint person_pk_pid primary key(pid)

);

Web-第二十四天 Oracle学习【悟空教程】_数据_136 

2.非空约束

使用非空约束,可以使指定的字段不可以为空。

范例:建立一张pid和name不可以为空的表

create table person(

       pid      number(10) not null,

       name     varchar2(10) not null,

       gender   number(1)  ,

       birthday date,

);

Web-第二十四天 Oracle学习【悟空教程】_oracle_137 

3.唯一约束(unique)

表中的一个字段的内容是唯一的

范例:建表一个name是唯一的表

create table person(

       pid      number(10) ,

       name     varchar2(10) unique,

       gender   number(1)  ,

       birthday date

);

Web-第二十四天 Oracle学习【悟空教程】_sql_138 

唯一约束的名字也可以自定义

create table person(

       pid      number(10) ,

       name     varchar2(10),

       gender   number(1)  ,

       birthday date,

       constraint person_name_uk unique(name)

);

Web-第二十四天 Oracle学习【悟空教程】_sql_139 

4.检查约束

使用检查约束可以来约束字段值的合法范围。

范例:创建一张表性别只能是1或2

create table person(

       pid      number(10) ,

       name     varchar2(10),

       gender   number(1)  check(gender in (1, 2)),

       birthday date

);

Web-第二十四天 Oracle学习【悟空教程】_sql_140 

检查约束也可以自定义

create table person(

       pid      number(10) ,

       name     varchar2(10),

       gender   number(1),

       birthday date,

       constraint person_gender_ck check(gender in (1,2))

);

Web-第二十四天 Oracle学习【悟空教程】_数据_141 

5.外键约束

之前所讲的都是单表的约束,外键是两张表的约束,可以保证关联数据的完整性。

范例:创建两张表,一张订单表,一张是订单明细表,订单和明细是一对多的关系

create table orders(

       order_id      number(10) ,

       total_price   number(10,2),

       order_time date,

      constraint orders_order_id_pk primary key(order_id)

);


create table order_detail(

       detail_id      number(10) ,

       order_id   number(10),

       item_name  varchar2(10),

       quantity   number(10),

      constraint order_detail_detail_id_pk primary key(detail_id)

);


insert into orders values(1, 200, to_date('2015-12-12','yyyy-MM-dd'));

insert into order_detail values(1, 2, 'java',1);

我们在两张表中插入如上两条数据,我们发现在order_detail表中插入的order_id在order表中并不存在,这样在数据库中就产生了脏数据。此时需要外键来约束它。


我们再次建表

create table orders(

       order_id      number(10) ,

       total_price   number(10,2),

       order_time date,

      constraint orders_order_id_pk primary key(order_id)

);


create table order_detail(

       detail_id      number(10) ,

       order_id   number(10),

       item_name  varchar2(10),

       quantity   number(10),

      constraint order_detail_detail_id_pk primary key(detail_id),

      constraint order_detail_order_id_fk foreign key(order_id) references orders(order_id)

);


Web-第二十四天 Oracle学习【悟空教程】_数据_142


外键关联一定注意:

外键一定是主表的主键

删表时一定先删子表再删主表,如果直接删主表会出现由于约束存在无法删除的问题

 Web-第二十四天 Oracle学习【悟空教程】_sql_143

但是可以强制删除drop table orders cascade constraint;(不建议)

删除主表的数据可以先删除子表的关联数据,再删主表,也可以使用级联删除。

级联删除在外键约束上要加上on delete cascade 如

constraint order_detail_order_id_fk foreign key(order_id)

      references orders(order_id) on delete cascade

这样删除主表数据的时候会把字表的关联数据一同删除

Web-第二十四天 Oracle学习【悟空教程】_sql_144


使用DML语句处理数据

插入数据

语法:INSERT  INTO表名[(列名1,列名2,...)]VALUES(值1,值2,...)

标准写法

Web-第二十四天 Oracle学习【悟空教程】_oracle_145 

简单写法(不建议)

INSERT  INTO 表名VALUES(值1,值2,...)

insert into person

values(1,'张三',1,'9-5月-1981','北京海淀');

注意:使用简单的写法必须按照表中的字段的顺序来插入值,而且如果有为空的字段使用null

insert into person values(2,'李四',1,null,'北京顺义');


更新数据

全部修改:UPDATE 表名 SET 列名1=值1,列名2=值2,....

局部修改:UPDATE 表名 SET 列名1=值1,列名2=值2,....WHERE 修改条件;

在update中使用子查询:

例如:给 NEW YORK地区的所有员工涨100员工资


update emp set sal=sal+100 where deptno

 in (select deptno from dept where loc='NEW YORK')



删除数据

语法 : DELETE FROM 表名​ ​WHERE​ ​删除条件;

在删除语句中如果不指定删除条件的话就会删除所有的数据

Truncate table实现数据删除

比较truncat与delete实现数据删除?

delete删除的数据可以rollback,也可以闪回

delete删除可能产生碎片,并且不释放空间

truncate是先摧毁表结构,再重构表结构

注意:插入、更新和删除会引起数据的变化。我们就必须考虑数据的完整性。


Oracle中的事务

这是因为oracle的事务对数据库的变更的处理,我们必须做提交事务才能让数据真正的插入到数据库中,在同样在执行完数据库变更的操作后还可以把事务进行回滚,这样就不会插入到数据库。如果事务提交后则不可以再回滚。

提交:commit

回滚:rollback


Oracle中事务的保存点:

Web-第二十四天 Oracle学习【悟空教程】_sql_146


事务的隔离级别和隔离性:

Web-第二十四天 Oracle学习【悟空教程】_oracle_147 

Oracle 支持的 3种事务隔离级别:READ COMMITED, SERIALIZABLE,READ ONLY. Oracle 默认的事务隔离级别为: READ COMMITED


管理其他数据库对象

视图

什么是视图:

视图就是封装了一条复杂查询的语句。

视图是一个虚表。

最大的优点就是简化复杂的查询。


创建视图的语法

Web-第二十四天 Oracle学习【悟空教程】_sql_148 

创建视图示例

范例:建立一个视图,此视图包括了20部门的全部员工信息

create view empvd20 as select * from emp t where t.deptno = 20

视图创建完毕就可以使用视图来查询,查询出来的都是20部门的员工

Web-第二十四天 Oracle学习【悟空教程】_sql_149


语法2:CREATE OR REPLACE VIEW 视图名称 AS 子查询

如果视图已经存在我们可以使用语法2来创建视图,这样已有的视图会被覆盖。

create or replace view empvd20 as select * from emp t where t.deptno = 20

不建议通过视图对表中的数据进行修改,因为会受到很多的限制。


序列

在很多数据库中都存在一个自动增长的列,如果现在要想在oracle 中完成自动增长的功能, 则只能依靠序列完成,所有的自动增长操作,需要用户手工完成处理。并且Oracle将序列值装入内存可以提高访问效率。


语法:

Web-第二十四天 Oracle学习【悟空教程】_oracle_150 

范例:

Web-第二十四天 Oracle学习【悟空教程】_oracle_151 

序列创建完成之后,所有的自动增长应该由用户自己处理,所以在序列中提供了以下的两种操作:

nextval :取得序列的下一个内容

currval :取得序列的当前内容


在插入数据时需要自增的主键中可以这样使用

Web-第二十四天 Oracle学习【悟空教程】_oracle_152


序列可能产生裂缝的原因:

回滚

系统异常

多个表共用一个序列


索引

索引是用于加速数据存取的数据对象。合理的使用索引可以大大降低i/o 次数,从而提高数据访问性能。

1.单列索引

单列索引是基于单个列所建立的索引,比如:

CREATE index 索引名  on 表名(列名)


2.复合索引

复合索引是基于两个列或多个列的索引。在同一张表上可以有多个索引,但是

要求列的组合必须不同,比如:

Create index emp_idx1 on emp(ename,job);

Create index emp_idx1 on emp(job,ename);


范例:给person表的name建立索引

create index pname_index on person(name);

范例:给person表创建一个name和gender的索引

create index pname_gender_index on person(name, gender);


3 .  索引测试

创建一个新表,向表中插入100W或500W条数据,记录查询一条数据所用时间,之后创建索引,后再查询一条数据,比较两条数据查询的时间。

--创建表

create table t_test(

tid number,

tname varchar2(30)

)


--创建序列

create sequence seq_test;


--插入数据

begin

for i in 1..5000000

loop

  insert into t_test values(seq_test.nextval,'测试数据'||i);

end loop;

commit;

end;


随便查询一条数据

select * from t_test where tname ='测试数据4789889'; 用时:  1.797s


--创建索引

create index index_test on t_test(tname)

select * from t_test where tname ='测试数据4889889';用时:  0.047


哈哈 ~ 效果还是很明显的嘛~


同义词

Web-第二十四天 Oracle学习【悟空教程】_sql_153 

例如:

Web-第二十四天 Oracle学习【悟空教程】_oracle_154 

使用同义词的作用?

可以很方便的访问其它用户的数据库对象

缩短了对象名字的长度


数据的导入导出

当我们使用一个数据库时,总希望数据库的内容是可靠的、正确的,但由于计算机系统的故障(硬件故障、软件故障、网络故障、进程故障和系统故障)影响数据库系统的操作,影响数据库中数据的正确性,甚至破坏数据库,使数据库中全部或部分数据丢失。因此当发生上述故障后,希望能重构这个完整的数据库该处理称为数据库恢复,而要进行数据库的恢复必须要有数据库的备份工作。


使用cmd命令整库导出与导入

在安装了oracle的电脑上执行

整库导出命令

exp system/javahelp full=y

添加参数full=y 表示整库导出

Web-第二十四天 Oracle学习【悟空教程】_数据_155 

执行命令后会在当前目录下生成一个叫EXPDAT.DMP,此文件为备份文件。

Web-第二十四天 Oracle学习【悟空教程】_oracle_156 

如果想指定备份文件的名称,则添加file参数即可,命令如下

exp system/javahelp file=C:\ javahelp.dmp full=y

Web-第二十四天 Oracle学习【悟空教程】_oracle_157


整库导入命令

imp system/javahelp full=y

此命令如果不指定file参数,则默认用备份文件EXPDAT.DMP 进行导入


如果指定file参数,则按照file指定的备份文件进行恢复

imp system/javahelp full=y file= C:\ javahelp.dmp


执行导入命令前需确保oracle数据库中无即将导入的对象,否则将报以下提示:

Web-第二十四天 Oracle学习【悟空教程】_oracle_158 


使用cmd命令按用户导出与导入

按用户导出

exp system/javahelp owner=javahelp001 file= c:\javahelp.dmp


按用户导入

imp system/javahelp file= c:\javahelp.dmp fromuser= javahelp001

使用cmd命令按表导出与导入

按表导出

exp javahelp001 /javahelp file= javahelp001.dmp tables=t_person,t_student

用tables参数指定需要导出的表,如果有多个表用逗号分割即可

按表导入

imp javahelp001/javahelp file= javahelp001.dmp tables= t_ person,t_student


使用PLSQL Developer导出数据

1:Tools→Export User Objects...选项,导出.sql文件。

说明:此操作导出的是建表语句

Web-第二十四天 Oracle学习【悟空教程】_sql_159 

2:Tools→Export Tables...导出表结构及数据

Web-第二十四天 Oracle学习【悟空教程】_oracle_160 

PL/SQL工具包含三种方式导出Oracle表结构及数据,三种方式分别为:Oracle Export 、SQL Inserts、PL/SQL Developer,下面分别简单介绍下区别:

第一种方式导出.dmp格式的文件,.dmp是二进制文件,可跨平台,还能包含权限,效率不错,用的最为广泛。


第二种方式导出.sql格式的文件,可用文本编辑器查看,通用性比较好,效率不如第一种,适合小数据量导入导出。尤其注意的是表中不能有大字段(blob,clob,long),如果有,会提示不能导出(提示如下: table contains one or more LONG columns cannot export in sql format,user Pl/sql developer format instead)。


第三种方式导出.pde格式的文件,.pde为PL/SQL Developer自有的文件格式,只能用PL/SQL Developer工具导入导出,不能用文本编辑器查看。


使用PLSQL Developer导入数据

导入数据之前最好把以前的表删掉,当然导入另外的数据库数据除外。

1:Tools→Import Tables...

Web-第二十四天 Oracle学习【悟空教程】_oracle_161 

2:根据对应格式,在不同界面选择即将导入的文件。

Web-第二十四天 Oracle学习【悟空教程】_数据_162 


PL/SQL编程语言

什么是PL/SQL?

PL/SQL(Procedure Language/SQL)

PLSQL是Oracle对sql语言的过程化扩展,指在SQL命令语言中增加了过程处理语句(如分支、循环等),使SQL语言具有过程处理能力。把SQL语言的数据操纵能力与过程语言的数据处理能力结合起来,使得PLSQL面向过程但比过程语言简单、高效、灵活和实用。

范例1:为职工涨工资,每人涨10%的工资。

update emp set sal=sal*1.1


范例2:例按职工的职称长工资,总裁涨1000元,经理涨800元,其他人员涨400元。


这样的需求我们就无法使用一条SQL来实现,需要借助其他程序来帮助完成,也可以使用pl/sql。


PL/SQL的语法

Web-第二十四天 Oracle学习【悟空教程】_数据_163 

常量和变量的定义

Web-第二十四天 Oracle学习【悟空教程】_oracle_164 

引用变量

Myname  emp.ename%type;

引用型变量,即my_name的类型与emp表中ename列的类型一样

在sql中使用into来赋值

declare 

  emprec emp.ename%type;

begin

  select t.ename into emprec from emp t where t.empno = 7369;

  dbms_output.put_line(emprec);

end;

记录型变量

Emprec  emp%rowtype

记录变量分量的引用

emp_rec.ename:='ADAMS';

declare

  p emp%rowtype;

begin

  select * into p from emp t where t.empno = 7369;

  dbms_output.put_line(p.ename || ' ' || p.sal);

end;


If语句

语法:

Web-第二十四天 Oracle学习【悟空教程】_数据_165 

范例1:如果从控制台输入1则输出我是1

declare

  pnum number := &num;

begin

  if pnum = 1 then

    dbms_output.put_line('我是1');

  end if;

end;


范例2:如果从控制台输入1则输出我是1否则输出我不是1

declare

  mynum number := &num;

begin

  if mynum = 1 then

    dbms_output.put_line('我是1');

  else

    dbms_output.put_line('我不是1');

  end if;

end;


范例3:判断人的不同年龄段18岁以下是未成年人,18岁以上40以下是成年人,40以上是老年人

declare

  mynum number := &num;

begin

  if mynum < 18 then

    dbms_output.put_line('未成年人');

  elsif mynum >= 18 and mynum < 40 then

    dbms_output.put_line('中年人');

  elsif mynum >= 40 then

    dbms_output.put_line('老年人');

  end if;

end;


循环

语法:

Web-第二十四天 Oracle学习【悟空教程】_sql_166


范例:使用语法1输出1到10的数字

declare

  step number := 1;

begin

  while step <= 10 loop

    dbms_output.put_line(step);

    step := step + 1;

  end loop;

end;


范例:使用语法2输出1到10的数字

declare

  step number := 1;

begin

  loop

    exit when step > 10;

    dbms_output.put_line(step);

    step := step + 1;

  end loop;

end;


范例:使用语法3输出1到10的数字

declare

  step number := 1;

begin

  for step in 1 .. 10 loop

    dbms_output.put_line(step);

  end loop;

end;



Oracle第四天

十一、PL/SQL编程语言

l 游标(光标Cursor)

为什么要使用游标?

Web-第二十四天 Oracle学习【悟空教程】_oracle_167 

在写java程序中有集合的概念,那么在pl/sql中也会用到多条记录,这时候我们就要用到游标,游标可以存储查询返回的多条数据。

语法:

CURSOR  游标名  [ (参数名  数据类型,参数名 数据类型,...)]  IS  SELECT   语句;


例如:cursor c1 is select ename from emp;

游标的使用步骤:

  • 打开游标:      open c1;    (打开游标执行查询)

  • 取一行游标的值:fetch c1 into pjob; (取一行到变量中)

  • 关闭游标:       close  c1;(关闭游标释放资源)

  • 游标的结束方式   exit when c1%notfound

  • 注意: 上面的pjob必须与emp表中的job列类型一致: 


定义:pjob emp.empjob%type;

范例1:使用游标方式输出emp表中的员工编号和姓名

declare

  cursor pc is

    select * from emp;

  pemp emp%rowtype;

begin

  open pc;

  loop

    fetch pc

      into pemp;

    exit when pc%notfound;

    dbms_output.put_line(pemp.empno || ' ' || pemp.ename);

  end loop;

  close pc;

end;


范例2:写一段PL/SQL程序,为部门号为10的员工涨工资。

declare

  cursor pc(dno myemp.deptno%type) is

    select empno from myemp where deptno = dno;

  pno myemp.empno%type;

begin

  open pc(20);

  loop

    fetch pc

      into pno;

    exit when pc%notfound;

    update myemp t set t.sal = t.sal + 1000 where t.empno = pno;

  end loop;

  close pc;

end;


例外

异常是程序设计语言提供的一种功能,用来增强程序的健壮性和容错性。

  • 系统定义异常 

no_data_found    (没有找到数据)

too_many_rows   (select …into语句匹配多个行)

zero_divide   ( 被零除)

value_error   (算术或换错误)

timeout_on_resource  (在等待资源时发生超时)


范例1:写出被0除的异常的plsql程序

declare

  pnum number;

begin

  pnum := 1 / 0;

exception

  when zero_divide then

    dbms_output.put_line('被0除');

  when value_error then

    dbms_output.put_line('数值换错误');

  when others then

    dbms_output.put_line('其他错误');

end;


  • 用户也可以自定义异常,在声明中来定义异常

DECLARE

My_job   char(10);

v_sal   emp.sal%type;

No_data    exception;

cursor c1 is select distinct job from emp    order by job;

如果遇到异常我们要抛出raise no_data;


范例2:查询部门编号是50的员工

declare

  no_emp_found exception;

  cursor pemp is

    select t.ename from emp t where t.deptno = 50;

  pename emp.ename%type;

begin

  open pemp;

  fetch pemp

    into pename;

  if pemp%notfound then

    raise no_emp_found;

  end if;

  close pemp;

exception

  when no_emp_found then

    dbms_output.put_line('没有找到员工');

  when others then

    dbms_output.put_line('其他错误');

end;


十二、存储过程

存储过程(Stored Procedure)是在大型数据库系统中,一组为了完成特定功能的SQL 语句集,经编译后存储在数据库中,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。存储过程是数据库中的一个重要对象,任何一个设计良好的数据库应用程序都应该用到存储过程。


创建存储过程语法:

create [or replace] PROCEDURE 过程名[(参数名 in/out 数据类型)]  

AS

begin

        PLSQL子程序体;

End;


或者


create [or replace] PROCEDURE 过程名[(参数名 in/out 数据类型)]  

is

begin

        PLSQL子程序体;

End  过程名;


范例1:给指定的员工涨100工资,并打印出涨前和涨后的工资

分析:我们需要使用带有参数的存储过程 

create or replace procedure addSal1(eno in number) is

  pemp myemp%rowtype;

begin

  select * into pemp from myemp where empno = eno;

  update myemp set sal = sal + 100 where empno = eno;

  dbms_output.put_line('涨工资前' || pemp.sal || '涨工资后' || (pemp.sal + 100));

end addSal1;


调用

begin

  ​-- Call the procedure

  addsal1(eno => 7902);     

  commit;

end;


十三、存储函数

create or replace function 函数名(Name in type, Name out type, ...) return 数据类型 is

  结果变量 数据类型;

begin


  return(结果变量);

end[函数名];


存储过程和存储函数的区别

一般来讲,过程和函数的区别在于函数可以有一个返回值;而过程没有返回值。 

但过程和函数都可以通过out指定一个或多个输出参数。我们可以利用out参数,在过程和函数中实现返回多个值。


范例:使用存储函数来查询指定员工的年薪

create or replace function empincome(eno in emp.empno%type) return number is

  psal  emp.sal%type;

  pcomm emp.comm%type;

begin

  select t.sal into psal from emp t where t.empno = eno;

  return psal * 12 + nvl(pcomm, 0);

end;


使用存储过程来替换上面的例子

create or replace procedure empincomep(eno in emp.empno%type, income out number) is

  psal emp.sal%type;

  pcomm emp.comm%type;

begin

  select t.sal, t.comm into psal, pcomm from emp t where t.empno = eno;

  income := ​psal​*12+nvl(pcomm,0);

end empincomep;


调用:

declare

  income number;

begin

  empincomep(7369, income);

  dbms_output.put_line(income);

end;


十四、Java程序调用存储过程

1.java连接oracle的jar包

可以在虚拟机中xp的oracle安装目录下找到jar包 :ojdbc14.jar

Web-第二十四天 Oracle学习【悟空教程】_数据_168 

2.数据库连接字符串


String driver="oracle.jdbc.OracleDriver";

String url="jdbc:oracle:thin:@192.168.56.10:1521:orcl";

String username="scott";

String password="tiger";



测试代码:

Web-第二十四天 Oracle学习【悟空教程】_数据_169 

3.实现过程的调用

1.调用过程

1.过程定义


--统计年薪的过程

create or replace procedure proc_countyearsal(eno in number,esal out number)

as

begin

   select sal*12+nvl(comm,0) into esal from emp where empno=eno;

end;


--调用

declare

   esal number;

begin

   proc_countyearsal(7839,esal);

   dbms_output.put_line(esal);

end;



2.过程调用


@Test

public void testProcedure01(){

String driver="oracle.jdbc.OracleDriver";

String url="jdbc:oracle:thin:@192.168.56.10:1521:orcl";

String username="scott";

String password="tiger";


try {

Class.forName(driver);

Connection con  = DriverManager.getConnection(url, username, password);


CallableStatement callSt = con.prepareCall("{call proc_countyearsal(?,?)}");


callSt.setInt(1, 7839);

callSt.registerOutParameter(2, OracleTypes.NUMBER);


callSt.execute();


System.out.println(callSt.getObject(2));

} catch (Exception e) {

e.printStackTrace();

}

}



4.游标引用的java测试

1.定义过程,并返回引用型游标


--定义过程

create or replace procedure proc_cursor_ref(dno in number,empList out sys_refcursor)

as

begin

  open empList for select * from emp where deptno = dno;

end;


--pl/sql中调用

declare

  mycursor_c sys_refcursor;

  myempc emp%rowtype;

begin

  proc_cursor_ref(20,mycursor_c);


  loop

    fetch mycursor_c into myempc;

    exit when mycursor_c%notfound;

    dbms_output.put_line(myempc.empno||','||myempc.ename);

  end loop;

  close mycursor_c;

end;



2.java代码调用游标类型的out参数


@Test

public void testFunction(){

String driver="oracle.jdbc.OracleDriver";

String url="jdbc:oracle:thin:@192.168.56.10:1521:orcl";

String username="scott";

String password="tiger";


try {

Class.forName(driver);

Connection con  = DriverManager.getConnection(url, username, password);


CallableStatement callSt = con.prepareCall("{call proc_cursor_ref (?,?)}");


callSt.setInt(1, 20);

callSt.registerOutParameter(2, OracleTypes.CURSOR);


callSt.execute();


ResultSet rs = ((OracleCallableStatement)callSt).getCursor(2);

while(rs.next()){

System.out.println(rs.getObject(1)+","+rs.getObject(2));

}

} catch (Exception e) {

e.printStackTrace();

}

}


思考:hibernate怎么调用存储过程.


十五、触发器

数据库触发器是一个与表相关联的、存储的PL/SQL程序。每当一个特定的数据操作语句(Insert,update,delete)在指定的表上发出时,Oracle自动地执行触发器中定义的语句序列。


1.触发器作用

  • 数据确认 

  • 示例:员工涨后的工资不能少于涨前的工资

  • 实施复杂的安全性检查

  • 示例:禁止在非工作时间插入新员工

  • 做审计,跟踪表上所做的数据操作等 

  • 数据的备份和同步 


2.触发器的类型 

  • 语句级触发器 :

在指定的操作语句操作之前或之后执行一次,不管这条语句影响了多少行 。 

  • 行级触发器(FOR EACH ROW) :

触发语句作用的每一条记录都被触发。在行级触发器中使用old和new伪记录变量, 识别值的状态。 


语法:

CREATE  [or REPLACE] TRIGGER  触发器名

   {BEFORE | AFTER}

   {DELETE | INSERT | UPDATE [OF 列名]}

   ON  表名

   [FOR EACH ROW [WHEN(条件) ] ]

declare

    ……

begin

   PLSQL  

End 触发器名


范例:插入员工后打印一句话“一个新员工插入成功”

create or replace trigger testTrigger

  after insert on person  

declare

  ​-- local variables here

begin

  dbms_output.put_line('一个员工被插入');

end testTrigger;


范例:不能在休息时间插入员工

create or replace trigger validInsertPerson

  before insert on person


declare

  weekend varchar2(10);

begin

  select to_char(sysdate, 'day') into weekend from dual;

  if weekend in ('星期一') then

    raise_application_error(-20001, '不能在非法时间插入员工');

  end if;

end validInsertPerson;

当执行插入时会报错

Web-第二十四天 Oracle学习【悟空教程】_sql_170


在触发器中触发语句与伪记录变量的值

触发语句

:old

:new

Insert

所有字段都是空(null)

将要插入的数据

Update

更新以前该行的值

更新后的值

delete

删除以前该行的值

所有字段都是空(null)

范例:判断员工涨工资之后的工资的值一定要大于涨工资之前的工资

create or replace trigger addsal4p

  before update of sal on myemp

  for each row

begin

  if :old.sal >= :new.sal then

    raise_application_error(-20002, '涨前的工资不能大于涨后的工资');

  end if;

end;


调用

update myemp t set t.sal = t.sal - 1;

Web-第二十四天 Oracle学习【悟空教程】_sql_171


3.触发器实际应用

需求:使用序列,触发器来模拟mysql中自增效果


1. 创建序列

    1).建立表

代码如下:

create table user  

(   

    id   number(6) not null,   

    name   varchar2(30)   not null primary key  

) ​ 


    2).建立序列SEQUENCE

代码如下:

create sequence user_seq;


2.创建自增的触发器

分析:创建一个基于该表的before insert 触发器,在触发器中使用刚创建的SEQUENCE。

代码如下:

create or replace trigger user_trigger   

before insert on user  

for each row   

begin  

      select   user_seq.nextval  into:new.id from sys.dual ;   

end;​  


3.测试效果

insert into javahelpuser(name) values('aa');

commit;

insert into javahelpuser(name) values('bb');

commit;


Web-第二十四天 Oracle学习【悟空教程】_sql_172

Web-第二十四天 Oracle学习【悟空教程】_sql_173Web-第二十四天 Oracle学习【悟空教程】_oracle_174

长按指纹,识别二维码,一键关注Java,大数据

Web-第二十四天 Oracle学习【悟空教程】_sql_175Web-第二十四天 Oracle学习【悟空教程】_oracle_174

长按指纹,识别二维码,一键关注Python

Web-第二十四天 Oracle学习【悟空教程】_oracle_177Web-第二十四天 Oracle学习【悟空教程】_oracle_174

长按指纹,识别二维码,一键关注产品经理