Web-第二十四天 Oracle学习【悟空教程】
Oracle应用开发实战
一、Oracle的基本概念和安装
l Oracle简介
ORACLE数据库系统是美国ORACLE公司(甲骨文)提供的以分布式数据库为核心的一组软件产品,是目前最流行的客户/服务器(CLIENT/SERVER)或B/S体系结构的数据库之一。比如SilverStream就是基于数据库的一种中间件。ORACLE数据库是目前世界上使用最为广泛的数据库管理系统,作为一个通用的数据库系统,它具有完整的数据管理功能;作为一个关系数据库,它是一个完备关系的产品;作为分布式数据库它实现了分布式处理功能。但它的所有知识,只要在一种机型上学习了ORACLE知识,便能在各种类型的机器上使用它。
l Oracle10g的安装
1. 解压oracle数据库安装包,如果是win7或者win8系统右键点击setup.exe选择兼容性,以xp方式,并且以管理员方式运行,以及其他所有用户都按着此规则如图
2. 如果是xp系统可以直接并双击解压目录下的setup.exe,出现安装界面,如下:
3. 输入口令和确认口令,如:javahelp,点击下一步,出现如下进度条,
注:此口令即是管理员密码。
4. 检查先决条件,选中红框所示的选择框,如下图:
5. 点击“下一步”,出现“概要”界面,点击“安装”。
6. 出现安装进度条,等待安装完成,如下图:
7. 安装完成后,自动运行配置向导,如下图,等待其完成:
8. 完成后,出现“口令管理”界面,点击“口令管理”,如下图:
9. 将SCOTT和HR用户的沟去掉(解锁这两个账户),如下图所示,点击“确定”:
10. 回到“口令管理”界面,点击“确定”,如下图:
11. 安装结束,点击“退出”。
l 虚拟网卡设置
本机和虚拟机之间能相互访问,它们的IP段必须相同,但是本机将会连接不同的网络环境(比如教室、宿舍、家庭),那么本机的IP段会产生变化就连不上虚拟机了,为了避免这种情况我们让本机和虚拟机之间用虚拟网卡的方式互相通信,配置方式参考如下文档:
l PLSQL Developer客户端工具的安装
1. 网络的测试
参考:
2. 安装PLSQL Developer客户端
3. 中文乱码的处理
二、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)。一个数据文件只能属于一个表空间。
l 用户:
用户是在实例下建立的。不同实例中可以建相同名字的用户。
注: 表的数据,是有用户放入某一个表空间的,而这个表空间会随机把这些表数据放到一个或者多个数据文件中。
由于oracle的数据库不是普通的概念,oracle是有用户和表空间对数据进行管理和存放的。但是表不是有表空间去查询的,而是由用户去查的。因为不同用户可以在同一个表空间建立同一个名字的表!这里区分就是用户了!
l SCOTT用户和HR用户
Oracle为了让学习者更好的进行学习,在安装成功后,也创建了初始的用户,其中SCOTT与HR就是初始的普通用户。这些用户下面都默认存在了表结构,我们重点掌握SCOTT用户下的所有表,如下所示:
SCOTT用户下的表
HR用户下的表
三、基本查询
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语句的语法格式和示例
1. 查询语法
Select * |列名 from 表名
2.别名用法
在查询的结果列中可以使用别名
Select 列名 别名,列名别名,... from emp;
别名中,有没有双引号的区别就在于别名中有没有特殊的符号或者关键字。
3.消除重复的数据
Select distinct *|列名, ... from emp;
使用distinct可以消除重复的行,如果查询多列的必须保证多列都重复才能去掉重复
4. 查询中四则运算
查询每个雇员的年薪
select ename, sal*12 from emp;
select ename, sal*12 income from emp;
Sql中支持四则运算“+,-,*,/”
l 什么是空值?
空值是无效的,未指定的,未知的或不可预知的值
空值不是空格或者0 。
注意:*、包含null的表达式都为null
*、空值永远不等于空值
l 连接符 ||
字符串连接查询
Mysql中实现方法:
查询雇员编号,姓名,工作
编号是:7369的雇员, 姓名是:smith,工作是:clerk
字符串的连接使用‘||’
四、条件查询和排序
l 使用where语句对结果进行过滤
l 比较运算符
l 其他比较运算符
l 逻辑运算符
l Where语句示例
1. 非空和空的限制
示例:查询每月能得到奖金的雇员
分析:只要字段中存在内容表示不为空,如果不存在内容就是null,
语法:列名 IS NOT NULL
为空 列名 IS NULL
范例:查询工资大于1500并且有奖金领取的雇员
分析:多个查询条件同时满足之间使用‘AND’
范例:查询工资大于1500或者有奖金的雇员
分析:多个查询条件或满足,条件之间使用“OR”
范例:查询工资不大于1500和没有奖金的人
语法:NOT(查询条件)
2.范围限制
范例:基本工资大于1500但是小于3000的全部雇员
分析:sal>1500, sal<3000
Between and等于 sal > =1500 and sal <= 3000
范例:查询1981-1-1到1981-12-31号入职的雇员
分析:between and 不仅可以使用在数值之间,也可以用在日期的区间
范例:查询雇员名字叫smith的雇员
在oracle中的查询条件中查询条件的值是区分大小写的
范例:查询雇员编号是7369,7499,7521的雇员编号的具体信息
如果使用之前的做法可以使用OR关键字
实际上,此时指定了查询范围,那么sql可以使用IN关键字
语法: 列名 IN (值1,值2,....)
列名 NOT IN (值1, 值2,...)
其中的值不仅可以是数值类型也可以是字符串
范例:查询雇员姓名是’SMITH’,’ALLEN’,’WARD’的雇员具体信息
3.模糊查询
在常用的站点中经常会有模糊查询,即:输入一个关键字,把符合的内容全部的查询出来,在sql中使用LIKE语句完成。
在LIKE中主要使用以下两种通配符
“%”:可以匹配任意长度的内容
“_”:可以匹配一个长度的内容
范例:查询出所有雇员姓名中第二个字符包含“M”的雇员
在LIKE中如果没有关键字表示查询全部
查询名字中带有“M”的雇员
在oracle中不等号的用法可以有两种形式“<>”和“!=”
范例:查询雇员编号不是7369的雇员信息
l 使用order by对结果排序
1.排序的语法
在sql中可以使用ORDER BY对查询结果进行排序
语法:SELECT * |列名 FROM 表名 {WEHRE 查询条件} ORDER BY 列名1 ASC|DESC,列名2...ASC|DESC
范例:查询雇员的工资从低到高
分析:ORDER BY 列名 默认的排序规则是升序排列,可以不指定ASC,如果按着降序排列必须指定DESC
如果存在多个排序字段可以用逗号分隔
注意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的函数?
l 函数的类型
l 单行函数
字符函数
示例:
接收字符输入返回字符或者数值,dual是伪表
1. 字符串的连接可以使用concat可以使用“||”建议使用“||”
concat('hello', 'world')
2. 字符串的截取,使用substr,第一个参数是源字符串,第二个参数是开始索引,第三个参数长度,开始的索引使用1和0效果相同
substr('hello', 1,3)
3. 获取字符串的长度
length('hello')
4. 字符串替换,第一个参数是源字符串,第二个参数被替换的字符串,第三个是替换字符串
replace('hello', 'l','x')
数值函数
日期函数
Oracle中的日期:
Oracle 中的日期型数据实际含有两个值 : 日期和时间。
默认的日期格式是 DD-MON-RR 。
日期的数学运算
在日期上加上或减去一个数字结果仍为日期
两个日期相减返回日期之间相差的天数
可以用数字除24
日期函数示例
1. 范例:查询雇员的进入公司的周数。
分析:查询雇员进入公司的天数(sysdate – 入职日期)/7就是周数
2. 获得两个时间段中的月数:MONTHS_BETWEEN()
范例:查询所有雇员进入公司的月数
3. 获得几个月后的日期:ADD_MONTHS()
范例:求出三个月后的日期
转换函数
TO_CHAR 函数对日期的转换
日期的格式:
TO_CHAR 函数对数字的转换
数字转换的格式:
TO_NUMBER和TO_DATE函数
示例:
1. TO_CHAR:字符串转换函数
范例:查询所有的雇员将将年月日分开,此时可以使用TO_CHAR函数来拆分
拆分时需要使用通配符
年:y, 年是四位使用yyyy
月:m, 月是两位使用mm
日:d, 日是两位使用dd
在结果中10以下的月前面被被补了前导零,可以使用fm去掉前导零
2. TO_NUMBER:数值转换函数
TO_NUMBER可以把字符串转换成数值
3. TO_DATE:日期转换函数
TO_DATE可以把字符串的数据转换成日期类型
通用函数
什么是通用函数?
这些函数适用于任何数据类型,同时也适用于空值
常用的通用函数
通用函数示例
1.空值处理nvl
范例:查询所有的雇员的年薪
我们发现很多员工的年薪是空的,原因是很多员工的奖金是null,null和任何数值计算都是null,这时我们可以使用nvl来处理。
条件表达式
什么是条件表达式?
在 SQL语句中使用IF-THEN-ELSE
实现的方式:
CASE 表达式:SQL99的语法,类似Basic,比较繁琐
DECODE 函数:Oracle自己的语法,类似Java,比较简介
CASE表达式
DECODE 函数
条件表达式示例: 根据10号部门员工的工资,显示税率
六、多行函数
l 什么是多行函数?
分组函数作用于一组数据,并对一组数据返回一个值。
也叫:组函数、分组函数
组函数会忽略空值;NVL 函数使分组函数无法忽略空值
l 常用的多行函数
l 多行函数示例
1.统计记录数count()
范例:查询出所有员工的记录数
不建议使用count(*),可以使用一个具体的列以免影响性能。
2.最小值查询min()
范例:查询出来员工最低工资
3.最大值查询max()
范例:查询出员工的最高工资
4.查询平均值avg()
范例:查询出员工的平均工资
5.求和函数sum()
范例:查询出20号部门的员工的工资总和
l 分组数据
范例:查询每个部门的人数
范例:查询出每个部门的平均工资
范例:查询出来部门编号,和部门下的人数
我们发现报了一个ORA-00937的错误
注意:
如果使用分组函数,SQL只可以把GOURP BY分组条件字段和分组函数查询出来,不能有其他字段。
如果使用分组函数,不使用GROUP BY 只可以查询出来分组函数的值
l 过滤分组数据
范例:查询出部门平均工资大于2000的部门
l WHERE和HAVING的区别
最大区别在于:where后面不能有组函数
Oracle第二天
七、多表查询
l 什么是笛卡尔积?
l Oracle的连接条件的类型
等值连接
不等值连接
外连接
自连接
l Oracle多表连接示例
1.多表连接基本查询
使用一张以上的表做查询就是多表查询
语法: SELECT {DISTINCT} *|列名.. FROM 表名 别名,表名1 别名
{WHERE 限制条件 ORDER BY 排序字段 ASC|DESC...}
范例:查询员工表和部门表
我们发现产生的记录数是56条,我们还会发现emp表是14条,dept表是4条,56正是emp表和dept表的记录数的乘积,我们称其为笛卡尔积。
如果多张表进行一起查询而且每张表的数据很大的话笛卡尔积就会变得非常大,对性能造成影响,想要去掉笛卡尔积我们需要关联查询。
在两张表中我们发现有一个共同的字段是depno,depno就是两张表的关联的字段,我们可以使用这个字段来做限制条件,两张表的关联查询字段一般是其中一张表的主键,另一张表的外键。
关联之后我们发现数据条数是14条,不在是56条。
多表查询我们可以为每一张表起一个别名
范例:查询出雇员的编号,姓名,部门的编号和名称,地址
范例:查询出每个员工的上级领导
分析:emp表中的mgr字段是当前雇员的上级领导的编号,所以该字段对emp表产生了自身关联,可以使用mgr字段和empno来关联
范例:在上一个例子的基础上查询该员工的部门名称
分析:只要在上一个例子基础上再加一张表的关联,使用deptno来做关联字段即可
范例:查询出每个员工编号,姓名,部门名称,工资等级和他的上级领导的姓名,工资等级
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
2.外连接(左右连接)
1). 右连接
当我们在做基本连接查询的时候,查询出所有的部门下的员工,我们发现编号为40的部门下没有员工,但是要求把该部门也展示出来,我们发现上面的基本查询是办不到的
使用(+)表示左连接或者右连接。
范例:查询出所有员工的上级领导
分析:我们发现使用我们以前的做法发现KING的上级领导没有被展示,我们需要使用外连接把他查询出来
如果用left join实现:
因为(+)这种形式是oracle数据库独有的,所以要求大家一定要掌握left join 或right join方式的写法。
八、子查询
l 什么是子查询?
使用子查询解决问题:谁的工资比SCOTT高?
l 子查询的语法
子查询 (内查询) 在主查询之前一次执行完成。
子查询的结果被主查询使用 (外查询)。
l 子查询的类型
l 单行子查询
只返回一条记录
单行操作符
单行子查询示例1
单行子查询示例2
单行子查询示例3
单行子查询示例4
范例:查询出比雇员7654的工资高,同时从事和7788的工作一样的员工
范例:要求查询每个部门的最低工资和最低工资的雇员和部门名称
非法使用单行子查询示例
l 多行子查询
返回了多条记录
多行操作符
l 子查询中的null值问题
单行子查询中的null值问题
多行子查询中的null值问题
示例:查询不是老板的员工
多行子查询中null值需要注意的问题:
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 找到员工表中工资最高的前三名,如下格式:
l 找到员工表中薪水大于本部门平均薪水的员工。
l 统计每年入职的员工个数
l 补充知识点:Oracle中的分页查询
ROWNUM:表示行号,实际上只是一个列,但是这个列是一个伪列,此列可以在每张表中出现。
ROWID:表中每行数据指向磁盘上的物理地址。
十、集合运算
l 什么是集合运算?
l 并集
范例:工资大于1500,或者是20号部门下的员工(并集)
select * from emp where sal>1500
union -- 或union all
select * from emp where deptno=20;
l 交集
范例:工资大于1500,并且是20号部门下的员工(交集)
select * from emp where sal>1500
intersect --交集
select * from emp where deptno=20;
l 差集
--范例: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、用户赋权限
新创建的用户没有任何权限,登陆后会提示
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权限,否则无法正常登陆
创建表
语法:
数据的类型:
使用子查询创建表的语法:
创建表范例:创建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是系统自动分配的约束的名字
主键不可为空
我们可以自己来指定主键约束的名字
create table person(
pid number(10),
name varchar2(10),
gender number(1) default 1,
birthday date,
constraint person_pk_pid primary key(pid)
);
2.非空约束
使用非空约束,可以使指定的字段不可以为空。
范例:建立一张pid和name不可以为空的表
create table person(
pid number(10) not null,
name varchar2(10) not null,
gender number(1) ,
birthday date,
);
3.唯一约束(unique)
表中的一个字段的内容是唯一的
范例:建表一个name是唯一的表
create table person(
pid number(10) ,
name varchar2(10) unique,
gender number(1) ,
birthday date
);
唯一约束的名字也可以自定义
create table person(
pid number(10) ,
name varchar2(10),
gender number(1) ,
birthday date,
constraint person_name_uk unique(name)
);
4.检查约束
使用检查约束可以来约束字段值的合法范围。
范例:创建一张表性别只能是1或2
create table person(
pid number(10) ,
name varchar2(10),
gender number(1) check(gender in (1, 2)),
birthday date
);
检查约束也可以自定义
create table person(
pid number(10) ,
name varchar2(10),
gender number(1),
birthday date,
constraint person_gender_ck check(gender in (1,2))
);
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)
);
外键关联一定注意:
外键一定是主表的主键
删表时一定先删子表再删主表,如果直接删主表会出现由于约束存在无法删除的问题
但是可以强制删除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
这样删除主表数据的时候会把字表的关联数据一同删除
使用DML语句处理数据
插入数据
语法:INSERT INTO表名[(列名1,列名2,...)]VALUES(值1,值2,...)
标准写法
简单写法(不建议)
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中事务的保存点:
事务的隔离级别和隔离性:
Oracle 支持的 3种事务隔离级别:READ COMMITED, SERIALIZABLE,READ ONLY. Oracle 默认的事务隔离级别为: READ COMMITED
管理其他数据库对象
视图
什么是视图:
视图就是封装了一条复杂查询的语句。
视图是一个虚表。
最大的优点就是简化复杂的查询。
创建视图的语法
创建视图示例
范例:建立一个视图,此视图包括了20部门的全部员工信息
create view empvd20 as select * from emp t where t.deptno = 20
视图创建完毕就可以使用视图来查询,查询出来的都是20部门的员工
语法2:CREATE OR REPLACE VIEW 视图名称 AS 子查询
如果视图已经存在我们可以使用语法2来创建视图,这样已有的视图会被覆盖。
create or replace view empvd20 as select * from emp t where t.deptno = 20
不建议通过视图对表中的数据进行修改,因为会受到很多的限制。
序列
在很多数据库中都存在一个自动增长的列,如果现在要想在oracle 中完成自动增长的功能, 则只能依靠序列完成,所有的自动增长操作,需要用户手工完成处理。并且Oracle将序列值装入内存可以提高访问效率。
语法:
范例:
序列创建完成之后,所有的自动增长应该由用户自己处理,所以在序列中提供了以下的两种操作:
nextval :取得序列的下一个内容
currval :取得序列的当前内容
在插入数据时需要自增的主键中可以这样使用
序列可能产生裂缝的原因:
回滚
系统异常
多个表共用一个序列
索引
索引是用于加速数据存取的数据对象。合理的使用索引可以大大降低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
哈哈 ~ 效果还是很明显的嘛~
同义词
例如:
使用同义词的作用?
可以很方便的访问其它用户的数据库对象
缩短了对象名字的长度
数据的导入导出
当我们使用一个数据库时,总希望数据库的内容是可靠的、正确的,但由于计算机系统的故障(硬件故障、软件故障、网络故障、进程故障和系统故障)影响数据库系统的操作,影响数据库中数据的正确性,甚至破坏数据库,使数据库中全部或部分数据丢失。因此当发生上述故障后,希望能重构这个完整的数据库该处理称为数据库恢复,而要进行数据库的恢复必须要有数据库的备份工作。
使用cmd命令整库导出与导入
在安装了oracle的电脑上执行
整库导出命令
exp system/javahelp full=y |
添加参数full=y 表示整库导出
执行命令后会在当前目录下生成一个叫EXPDAT.DMP,此文件为备份文件。
如果想指定备份文件的名称,则添加file参数即可,命令如下
exp system/javahelp file=C:\ javahelp.dmp full=y |
整库导入命令
imp system/javahelp full=y |
此命令如果不指定file参数,则默认用备份文件EXPDAT.DMP 进行导入
如果指定file参数,则按照file指定的备份文件进行恢复
imp system/javahelp full=y file= C:\ javahelp.dmp |
执行导入命令前需确保oracle数据库中无即将导入的对象,否则将报以下提示:
使用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文件。
说明:此操作导出的是建表语句
2:Tools→Export Tables...导出表结构及数据
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...
2:根据对应格式,在不同界面选择即将导入的文件。
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的语法
常量和变量的定义
引用变量
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语句
语法:
范例1:如果从控制台输入1则输出我是1
declare
pnum number := #
begin
if pnum = 1 then
dbms_output.put_line('我是1');
end if;
end;
范例2:如果从控制台输入1则输出我是1否则输出我不是1
declare
mynum number := #
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 := #
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;
循环
语法:
范例:使用语法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)
为什么要使用游标?
在写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
2.数据库连接字符串
String driver="oracle.jdbc.OracleDriver"; String url="jdbc:oracle:thin:@192.168.56.10:1521:orcl"; String username="scott"; String password="tiger"; |
测试代码:
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;
当执行插入时会报错
在触发器中触发语句与伪记录变量的值
触发语句 | :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;
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;
长按指纹,识别二维码,一键关注Java,大数据
长按指纹,识别二维码,一键关注Python
长按指纹,识别二维码,一键关注产品经理