Oracle

本篇内容较多大家可以分几次看

1.Oracle简介

公司“甲骨文”,全球第一大数据库数据库厂商,第二大独立软件供应商

一:发展史

1970年    数据库起家

1980年    ORACLE6版本

1990年    ORACLE7版本,多元化产品,以数据库为优先发展方向

1995年    ORACLE8版本

1999年    ORACLE8i版本

2001年    ORACLE9i release1

2002年    ORACLE9i release2

2003年    ORACLE10g版本

2007年    ORACLE11g版本

2009 年    甲骨文以每股9.5美元价格收购Sun公司总交易额74美元

二:近些版本的特点

Oracle10g

1)支持网格计算(grid)达到负载均衡:多台节点服务器利用高速网络组成一个虚拟的高性能服务器,负载在整个网格中均衡,避免单点故障

2)安装比9i工作量减少一半

3)新增浏览器的企业管理器(Enterprise Manager

Oracle11g

.........

Oracle12g

........

 

2.Oracle安装

一:系统要求(一般我们现在的电脑都满足这些条件)

操作系统最好是windows server

内存最好是256M

硬盘空间最好是2G以上

二:官网下的

3.Oracle卸载

一:停止所有与Oracle相关的服务

二:使用OUIOracle Universal Installer)卸载Oracle软件。

 开始->程序->Oracle-OraDb110g_home1|Oracle installation product|Universal installer.

三:删除注册表中的内容运行regedit命令,删除下面内容:

HKEY_LOCAL_MACHINE|SOFTWARE|ORACLE注册表键,删除此键。

  HKEY_LOCAL_MACHINE|SYSTEM|CurrentControlSet|Services,删除Services键下所有以oracle为首的键。

HKEY_LOCAL_MACHINE|SYSTEM|CurrentControlSet|Services|Eventlog|Application, 删除此键下所有以oracle为首的键。 

  HKEY_CLASSES_ROOT,删除此键下所有以OraOracleOrclEnumOra 为前缀的键。

  HKEY_CURRENT_USER|Software| Microsoft|Windows|CurrentVersion|Explorer|MenuOrder|Start Menu|Programs, 删除此键下所有以oracle为首的键。

  HKEY_LOCAL_MACHINE|SOFTWARE|ODBC|ODBCINST.INI注册表键,删除了Microsoft ODBC FOR ORACLE注册表键以外的所有有Oracle字样的键值。

  HKEY_LOCAL_MACHINE|SYSTEM|CurrentControlSet|Services,删除以OracleOraWeb为前缀的键。

三:删除环境变量,PATH中含有Oracle的位置信息都删了

四:文件系统中删除Oracle相关的文件与目录(app目录,CProgram FilesOracle

如果C盘下的Oracle删不了重启计算机即可

4.Oracle学习

一:注意Oracle安装会自动的生成sys用户和system用户:

sys用户是超级用户,具有最高权限,具有sysdba角色,有create database的权限,该用户默认的密码是change_on_install

system用户是管理操作员,权限也很大。具有sysoper角色,没有create database的权限,默认的密码是manager

一般讲,对数据库维护,使用system用户登录就可以拉

也就是说syssystem这两个用户最大的区别是在于有没有create database的权限。

二:管理工具

Sql*plus

在开始->程序->oracle oradb_home10g->application development->sql*plus

在运行栏中输入: sqlplusw即可

Sqlplus

Dos下的Oracle管理工具功能与sql*plus相似

在运行栏中输入 sqlplus;在oracle主目录ora10ginsqlplus.exe

Pl/sql developer

第三方软件,主要用于开发,测试,优化oracle

Enterprise manager console(企业管理器)

Web管理Oracle,一般端口号为11585500

URLhttp://机器名:端口/em

 

三:基本命令

Sql*plus常用命令

1)连接命令

连接数据库:Conn[ection] 用户名/密码@网络服务名 [as sysdba[sysoper]]

断开数据库:disc[onnect]

修改密码:  passw[ord]

退出:exit

2)文件操作命令

Start /@:运行sql脚本

sql>@ d:a.sql或是sql>start d:a.sql

Spool 将命令开始到spool off间的内容输出到指定文件中

Sql>spool 要存放的文件地址(此时开始记录命令窗口中的命令)-spool off(存到指定文件的命令结束此时查看文件发现出现了很多命令)

Edit:编辑sql文件

3)交互式命令

&可以弹出窗口让我们自己填

Select * from emp where job=&job;

Spool:将命令窗口中的命令存到指定文件中

4)显示设置环境变量

用来控制输出的各种格式如果希望永久的保存相关的设置,可以去修改glogin.sql脚本

Linesize:set/show Linesize 查看设置输出一行宽度默认80

Pagesize: set/show Pagesize 查看设置输出一页行数默认14

4)用户管理

注意:权限,角色,数据对象的解释

权限分为系统权限,对象权限;系统权限:对数据库的相关操作(建用户,赋权限等),对象权限对数据对象的相关操作(select,insert,update,delete,all;

角色是将权限封装在一起

1)创建用户

创建用户需要有dba权限才可以做(sys/system用户)

A.简单方式

Create user 名字 identified by 密码

B.复杂方式

Create user 名字 identified by 密码

Default tablespace 默认表空间名

Temporary tablespace 临时的表空间名

Quota 最大用户可创建数据对象(表,索引,视图)

2)修改密码

自己修改密码没问题;别人修改密码需要有dba权限或者有修改用户的系统权限

自己:Password 用户名

别人:alter user 用户名 identified by 新密码

3)删除用户

Dba权限或者有alter user系统权限

Dorp user 用户名【cascade】如果用户创建过表需要加上cascade

4)赋权限

希望xiaoming用户可以去查询emp
希望xiaoming用户可以去查询scottemp
     grant select on emp to xiaoming
希望xiaoming用户可以去修改scottemp
  grant update on emp to xiaoming
希望xiaoming用户可以去修改/删除,查询,添加scottemp
  grant all on emp to xiaoming
scott希望收回xiaomingemp表的查询权限
  revoke select on emp from xiaoming

小明也想将对象权限(select on Scott.emp)分配给xiaohong

Scott xiaoming赋权限时加with grant options

grant select on emp to xiaoming with grant option;

如果Scott将对象权限从xiaoming这撤销了,小红从xiaoming那获得对象权限也就没有了 

5)使用profile管理用户口令

Profile:是口令限制,资源限制的命令集合,当建立数据时,Oracle会自动创建default默认的profile文件,当创建用户如果没有指定profile,系统会默认指定defaultprofile文件

A.账户锁定

概述:指定scott用户最多只能尝试三次登录,锁定时间2

SQL>create profile lock_account limit failed_login_attempts 3 password_lock_time 2;
SQL> alter user scott profile lock_account; B账户解锁

Alter user 被锁定的用户名 account unlock;

C.终止口令

概述:要用户每隔10天修改自家密码,宽限期2

SQL> create profile myprofile limit password_life_time 10 password_grace_time 2;
SQL> alter user 用户名profile myprofile;

D.口令历史

概述:当希望用户在修改密码时不使用以前的密码可使用口令历史,这样Oracle就会将口令的修改存到口令字典中,下次再更改密码时就会与旧密码作对照

SQL>create profile password_history limit password_life_time 10 password_grace_time 2 password_reuse_time 10
password_reuse_time //指定口令可重用时间即10天后就可以重用

E.删除profile

          SQL> drop profile password_history casade
          注意:文件删除后,用这个文件去约束的那些用户通通也都被释放了。

          加了casade,就会把级联的相关东西也给删除掉

------------------------------------------休息一下------------------------------------------------

四:表管理

  1)创建表

    Create table 表名(field1 datatype,field2 datatype)

    A:数据类型解析    

分类 数据类型 说明
文本,二进制类型

char(20)

varchar2(20)

nchar(20)

nvarchar2(20)

clob(character large object)

blob(binary large object)

 

定长 最大2000字符

变长 最大4000字符

Unicode数据类型 ,定长 最大2000字符

Unicode数据类型 ,变长 最大4000字符

字符型大对象 ,最大8tb

二进制数据 可以存放图片/声音 8tb

数值类型 number(p,s)  p:整数位;s:小数位

范围: 1 <= p <=38, -84 <= s <= 127 保存数据范围:-1.0e-130 <= number value < 1.0e+126 保存在机器内部的范围: 1 ~ 22 bytes

时间日期

data

timestamp(n)

 包含年月日,时分秒。默认格式:DD-MON-YYYY。从公元前4712年1月1日到公元4712年12月31日的所有合法日期

n的取值为0~9.表示指定TIMESTAMP中秒的小数位数。N为可选。如果n为0,timestamp与date等价[不推荐]

 

 

 

 

 

 

 

 

 

 

 

 

 

      

      表名和列的命名规则

        必须以字母开头

        长度不能超过30个字符

        不能使用oracle的保留字

        只能使用如下字符 A-Z,a-z,0-9,$,#等

    数值类型小习题:

      

       例子:

1.创建两个表
create table student (    ---表名 
          xh       number(4),   --学号 
          xm    varchar2(20),   --姓名 
          sex      char(2),     --性别 
          birthday date,         --出生日期 
          sal      number(7,2)   --奖学金 
); 
--班级表 
CREATE TABLE class( 
    classId NUMBER(2), 
    cName VARCHAR2(40) 
); 
2.修改表
 添加一个字段
 alter table student add(classId number(2));
 修改一个字段长度
  alter table student modify(xm varchar2(30));
 修改字段类型或者名称(不能有数据)不建议这么做
  alter table student modify(xm char(30));
 删除一个字段 不建议这么做因为删了顺序就变了,加就没问题,加是加在后面
   alter table student drop column sal;
 修改表名 很少有这种需求
    rename table student to stu;
 删除表
    drop table student;
3.添加数据
所有字段都插入数据
修改日期的默认格式(临时修改,数据库重启后仍为默认;如要修改需要修改注册表)
修改后,可以用我们熟悉的格式添加日期类型:
插入部分字段n 
插入空值
如果要查询student表中birthday为null的记录怎么写sql?
4.修改数据
用Update关键字
5.删除数据
Delete:删除数据结构还在数据还可以恢复因为它写日志所有速度慢,只需创建还原点savepoint a;处理的操作;rollback to a;
drop:删除数和结构不写日志所以速度快,不能恢复

五:查询

新安装的数据库中scott用户拥有的表(emp,dept)我们可以那他们做例子

    1)oracle表基本查询    

1.查看表结构
  desc emp;
2.查询指定列
  这里值得一说的是distinct函数消除重复行
3.打开显示操作时间的开关
  set timing on(测试后发现不能用不知道怎么回事)
4.nvl,显示每个雇员的年工资
思路:每位雇员每月可能还有奖金可能没有就出现null值解决null的问题就需要用到nvl函数了
解决:select a.sal*13+nvl(a.comm,0) "年薪",a.ename,a.comm from emp a
View Code
5.like使用:%:表示0到多个字符  _:表示任意单个字符
6.where条件中使用in
SELECT * FROM emp WHERE empno in (7844, 7839,123,456); 
7.is null
SELECT * FROM emp WHERE mgr is null;
8.order by 字段:排序默认asc
问题:按照部门号升序而雇员的工资降序排列
SELECT * FROM emp ORDER by deptno, sal DESC; 
  还可以使用列的别名来排序
select ename, (sal+nvl(comm,0))*12 "年薪" from emp order by "年薪" asc; 
9.clear清屏

  2)oracle复杂查询

1.数据分组--max,min,avg,sum,count
注意:select ename, max(sal) from emp;这语句执行的时候会报错,因为那里需要一样max是分组函数,ename不是
2.group by 和having子句
  group by 对查询结果分组统计,having限制分组显示结果
    问题:如何显示每个部门的平均工资和最高工资?
思路,每个部门明显分组用到group by
select max(sal),min(sal),a.deptno from emp a group by a.deptno;
View Code

   问题:显示每个部门的每种岗位的平均工资和最低工资?

思路:每个部门的每种岗位两个分组
select max(sal),min(sal) ,a.empno,a.job from emp a group by a.empno,a.job
View Code

    问题:显示平均工资低于2000的部门号和它的平均工资?

SELECT AVG(sal), MAX(sal), deptno FROM emp GROUP by deptno having AVG(sal) < 2000;
View Code

 对数据分组的总结
  分组函数只能出现在选择列表、havingorder by子句中(不能出现在where)
  如果在select语句中同时包含有group by, having, order by 那么它们的顺序是group by, having, order by
  在选择列中如果有列、表达式和分组函数,那么这些列和表达式必须有一个出现在group by 子句中,否则就会出错。
    如SELECT deptno, AVG(sal), MAX(sal) FROM emp GROUP by deptno HAVING AVG(sal) < 2000;
    这里deptno就一定要出现在group by 中 

3.多表查询 

  规定:多表查询的条件是 至少不能少于 表的个数-1 才能排除笛卡尔集

  问题:显示部门号为10的部门名、员工名和工资?

思路:两表查询,两表建立连接,一个成员在莫一段位置
select a.ename,a.sal,b.grade from emp a,salgrade b where a.sal between b.losal and b.hisal;
View Code  

  问题:显示雇员名,雇员工资及所在部门的名字,并按部门排序?

 select a.ename,a.sal,b.dname from emp a,dept b where a.empno=b.deptno order by a.empno

  (注意:如果用group by,一定要把e.deptno放到查询列里面)

4.自连接

  同一张表的连接查询

  问题:显示某个员工的上级领导的姓名?

思路:这两表关键就是a表的mgr和b表ename要相同
SELECT worker.ename, boss.ename FROM emp worker,emp boss WHERE worker.mgr = boss.empno AND worker.ename = 'FORD';
View Code

5.子查询 

  请思考:如何查询和部门10的工作相同的雇员的名字、岗位、工资、部门号 

select * from emp where job in(select distinct job  from emp a where a.deptno=10)
View Code 

  A:多行子查询

  在多行子查询中使用all操作符 

  问题:如何显示工资比部门30的所有员工的工资高的员工的姓名、工资和部门号?

select * from emp a where a.sal>all(select sal from emp b where b.deptno=30 ) 
View Code

  执行效率上, 函数高得多

  在多行子查询中使用any操作符

  问题:如何显示工资比部门30的任意一个员工的工资高的员工姓名、工资和部门号? 

SELECT ename, sal, deptno FROM emp WHERE sal > ANY (SELECT sal FROM emp WHERE deptno = 30); 
View Code

  B:多列子查询(查询结果多个列)多列多行查询的区别是:查询条件是一列和多列的区别

  请思考如何查询与SMITH的部门和岗位完全相同的所有雇员。 

select * from emp a where (a.deptno,a.job)=(select deptno, job from emp where ename='SMITH' ) 
View Code

  如何显示高于自己部门平均工资的员工的信息(很难的多想想)

思路:看到这个题目一般大家都是蒙的,需要查分下,这里肯定是有子查询的,找到子查询,“自己部门平均工资”即可变为查询各个部门平均工资—》之后再原表与此表多表查询就很简单了
select a.ename,a.sal,b.mysal from emp a,(select avg(sal) mysal,deptno from emp group by deptno) b where a.deptno=b.deptno and a.sal>b.mysal
View Code

 注意:(给表取别名的时候,不能加as;但是给列取别名,是可以加as的) 

   3)分页查询

按雇员的id号升序取出
oracle的分页一共有三种方式
    1.根据rowid来分
      select * from t_xiaoxi where rowid in (select rid from (select rownum rn, rid from(select rowid rid, cid from t_xiaoxi order by cid desc) where rownum<10000) where rn>9980) order by cid desc;
    执行时间0.03
    2.按分析函数来分
      select * from (select t.*, row_number() over(order by cid desc) rk from t_xiaoxi t) where rk<10000 and rk>9980;
    执行时间1.01
    3.rownum来分
      select * from (select t.*,rownum rn from(select * from t_xiaoxi order by cid desc)t where rownum<10000) where rn>9980;
    执行时间0.1秒 

    应用最多的是rownum来分比较容易理解

例如工资排序后查询6-10条数据

select * from (select a.*,rownum rn from (select * from emp order by sal) a where rownum<=10) where rn>=6

这里要先截取大行再封住小行从而获得分页效果

  4)自我复制数据(蠕虫复制)

insert into mytable (id,name,sal,job,deptno)

select id,name,sal,job,deptno from mytable;

执行多次就能获得大数据

6.合并查询

多用于数据量大的合并多个查询结果

unionunion allintersectminus

Union:保留相同的;

Union all:全部保留;

Intersect:取得两个结果集的交集

Minus:相当于做减法

7.内连接外连接

内连接:where两表查询就相当于内连接

外连接:left jion,right jion,

8.创建数据库实例

1). 通过oracle提供的向导工具。
     database Configuration Assistant  【数据库配置助手】
  2).我们可以用手工步骤直接创建。

------------------------------------休息一下----------------------------------------------------

 

1.java操作Oracle

 

jdk从1.8开始,删除了jdbc-odbc桥,所以odbc的驱动是用不了的,建议重新安装jdk1.7或者更低的版本

加载驱动之前需要导入jar包安装Oracle后在D:OracleappAdministratorproduct11.2.0dbhome_1jdbclib中找ojdbc.jar

//加载驱动


Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");

//得到连接

Connection ct=DriverManager.getConnection("jdbc.odbc:testConnectOracle","scott","scott");


//这里过后与SQL Server查询一样了

Statement sm=ct.createStatement();

ResultSet  rs=sm.executeQuery("select * from emp");

while(rs.next()){

System.out.println("用户:"+rs.getString(2));

}

再创建连接之前需要配置ODBC点击控制面板-->系统和安全-->管理工具-->数据源(ODBC),打开后点添加,如图:

可以看到,有个Oracle in OraDb10g_home1的驱动,它e安装完后自动加上去的。 选中后,点完成,再填如下信息,如图:
这样配好后基本就可以了,但为了安全起见,建议大家测试一下,点击 Test Connection按钮, 测试通过后点ok,然后数据源就生成了图:

然后把数据源名称写进jdbc.odbc:里。

这里要注意:jdbcodbc能不能远程连接呢?不能远程连接,也就是你这样写的话就意味着java程序和oracle数据库应该是在同一台机器上,因为这里没有指定IP地址,肯定默认就是本地。如果要远程连,就用jdbc,jdbc是可以远程连的。

//jdbc模式可以远程连接的

//加载驱动


Class.forName("oracle.jdbc.driver.OracleDriver");

//得到连接

Connection ct=DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:orclbc:testConnectOracle","scott","scott");


//这里过后与SQL Server查询一样了

Statement sm=ct.createStatement();

ResultSet  rs=sm.executeQuery("select * from emp");

while(rs.next()){

System.out.println("用户:"+rs.getString(2));

}

2.使用特定的格式插入日期值

To_data(1998-09-12,YYYY-MM-DD)

3.Oracle中的事务处理

当执行事务操作时(dml语句),oracle会在被作用的表上加锁,防止其它用户修改表的结构。这里对我们的用户来来讲是非常重要的。
.....其它进程排序,知道1号进程完成,锁打开,2号进程进入。依次进行,如果有进程级别较高的,可以插队。

当执行用commit语句可以提交事务

事务的几个重要操作n 
设置保存点 savepoint a
取消部分事务 rollback to a
取消全部事务 rollback

注意:这个回退事务,必须是没有commit前使用的;如果事务提交了,那么无论你刚才做了多少个保存点,都统统没有。
如果没有手动执行commit,而是exit了,那么会自动提交

例子:

Connection ct=null;

try {

Class.forName("oracle.jdbc.driver.OracleDriver");


ct = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:orcl","scott","tiger");

//加入事务

ct.setAutoCommit(false);//设置默认不能提交

 

Statement sm=ct.createStatement();

sm.execute("update emp set sal=sal-100 where ename='SCOTT'");

int i=7/0;

//给smith的sal加上100

sm.executeUpdate("update emp set sal=sal+100 where ename='SMITH'");

ct.commit();//提交事务

//关闭资源

sm.close();

ct.close();

} catch (Exception e) {

// TODO Auto-generated catch block

try {

ct.rollback();

} catch (SQLException e1) {

// TODO Auto-generated catch block

e1.printStackTrace();

}

e.printStackTrace();

}
View Code

设置只读事务

set transaction read only;

 

4.Oracle中的函数

1)字符函数

lower(char)

upper(char)

length(char)

substr(char,m,n):取字符串的子串n代表取n个的意思

replace(char1,search_string,replace_string)

instr(char1,char2,[,n[,m]])取子串在字符串的位置

2)数学函数

cos,cosh,exp,ln, log,sin,sinh,sqrt,tan,tanh,acos,asin,atan,round,

常用的:

Round(n,[m]):四舍五入

trunc(n,[m]): 截取数字

mod(m,n) :取m,n的模

floor(n) 返回小于或是等于n的最大整数
 ceil(n) 返回大于或是等于n的最小整数

对数字的处理,在财务系统或银行系统中用的最多,不同的处理方法,对财务报表有不同的结果

3)日期函数

默认情况下日期格式是dd-mon-yy 即12-7月-78

Sysdata:放回系统时间

Add_months(d,n)在d日期后加n个月后的日期

last_day(d):返回指定日期所在月份的最后一天

问题:查找已经入职8个月多的员工
SQL> select * from emp where sysdate>=add_months(hiredate,8);
问题:显示满10年服务年限的员工的姓名和受雇日期。
SQL> select ename, hiredate from emp where sysdate>=add_months(hiredate,12*10);
问题:对于每个员工,显示其加入公司的天数。
SQL> select floor(sysdate-hiredate) "入职天数",ename from emp;
or
SQL> select trunc(sysdate-hiredate) "入职天数",ename from emp;
问题:找出各月倒数第3天受雇的所有员工。
SQL> select hiredate,ename from emp where last_day(hiredate)-2=hiredate;

4)转换函数

Oracle提供默认的转换但是默认的功能不足

转换函数就能解决我们的问题了

To_char()

问题:日期是否可以显示 /分/秒
SQL> select ename, to_char(hiredate, 'yyyy-mm-dd hh24:mi:ss') from emp;
问题:薪水是否可以显示指定的货币符号
SQL>


yy:两位数字的年份 2004-->04
yyyy:四位数字的年份  2004年
mm:两位数字的月份 8月-->08
dd:两位数字的天 30号-->30
hh24: 8点-->20
hh12:8点-->08
mi、ss-->显示分钟秒

9:显示数字,并忽略前面0
0:显示数字,如位数不足,则用0补齐
.:在指定位置显示小数点
,:在指定位置显示逗号
$:在数字前加美元
L:在数字前面加本地货币符号
C:在数字前面加国际货币符号
G:在指定位置显示组分隔符、
D:在指定位置显示小数点符号(.)

问题:显示薪水的时候,把本地货币单位加在前面
SQL> select ename, to_char(hiredate, 'yyyy-mm-dd hh24:mi:ss'), to_char(sal,'L99999.99') from emp;
问题:显示1980年入职的所有员工
SQL> select * from emp where to_char(hiredate, 'yyyy')=1980;
问题:显示所有12月份入职的员工
SQL> select * from emp where to_char(hiredate, 'mm')=12;

to_daten 
函数to_date用于将字符串转换成date类型的数据。

  5)系统函数
    sys_contextn 
    terminal:当前会话客户所对应的终端的标示符
    lanuage: 语言
    db_name: 当前数据库名称
    nls_date_format: 当前会话客户所对应的日期格式
    session_user: 当前会话客户所对应的数据库用户名
    current_schema: 当前会话客户所对应的默认方案名
    host: 返回数据库所在主机的名称
    通过该函数,可以查询一些重要信息,比如你正在使用哪个数据库?
    select sys_context('USERENV','db_name') from dual;
    注意:USERENV是固定的,不能改的,db_name可以换成其它,比如select sys_context('USERENV','lanuage') from dual;又比如select sys_context('USERENV','current_schema') from dual;

------------------------------------休息一下---------------------------------------------

5.数据库管理,表的逻辑备份与恢复

  

  最大区别:sysdba可以创建数据库,sysoper不可以创建数据库

  sysdba>sysoper>dba

  1)调试优化 数据库

    管理数据库参数可以调试数据库

  2) 显示初始化参数
    show parameter命令
       如何修改参数
    D:oracleadminmyoralpfileinit.ora文件中去修改比如要修改实例的名字

  3)数据库(表)的逻辑备份与恢复

    在导入和导出的时候,要到oracle目录的bin目录下

    A:导出:

      导出具体的分为:导出表,导出方案,导出数据库三种方式。
      导出使用exp命令来完成的,该命令常用的选项有:
        userid: 用于指定执行导出操作的用户名,口令,连接字符串
        tables: 用于指定执行导出操作的表
        owner        用于指定执行导出操作的方案
        full=y: 用于指定执行导出操作的数据库
        inctype: 用于指定执行导出操作的增量类型
        rows: 用于指定执行导出操作是否要导出表中的数据
        file: 用于指定导出文件名

      例子:

       导出表

xp userid=scott/tiger@myoral tables=(emp,dept) file=d:e1.dmp 
2.导出其它方案的表 
如果用户要导出其它方案的表,则需要dba的权限或是exp_full_database的权限,比如system就可以导出scott的表 
E:oracleora92in>exp userid=system/manager@myoral tables=(scott.emp) file=d:e2.emp 
特别说明:在导入和导出的时候,要到oracle目录的bin目录下。 
3. 导出表的结构 
exp userid=scott/tiger@accp tables=(emp) file=d:e3.dmp  rows=n 
4. 使用直接导出方式 
exp userid=scott/tiger@accp tables=(emp) file=d:e4.dmp  direct=y 
这种方式比默认的常规方式速度要快,当数据量大时,可以考虑使用这样的方法。 
这时需要数据库的字符集要与客户端字符集完全一致,否则会报错... 
View Code
  1. 导出自己的方案
    exp userid=scott/tiger@myorcl owner=scott file=d:scott.dmp
    2. 导出其它方案
    如果用户要导出其它方案,则需要dba的权限或是exp_full_database的权限,比如system用户就可以导出任何方案
    3.导出数据库

    exp userid=system/manager@myorcl owner=(system,scott) file=d:system.dmp

    增量备份(好处是第一次备份后,第二次备份就快很多了)

    B:导入

      imp常用的选项有
      userid: 用于指定执行导入操作的用户名,口令,连接字符串
      tables: 用于指定执行导入操作的表
      formuser: 用于指定源用户
      touser: 用于指定目标用户
      file: 用于指定导入文件名
      full=y: 用于指定执行导入整个文件
      inctype: 用于指定执行导入操作的增量类型
      rows: 指定是否要导入表行(数据)
      ignore: 如果表存在,则只导入数据

exp userid=system/manager@myorcl full=y inctype=complete file=d:all.dmp

      1. 导入自己的表 
        imp userid=scott/tiger@myorcl tables=(emp) file=d:xx.dmp 
      2. 导入表到其它用户 
        要求该用户具有dba的权限,或是imp_full_database 
        imp userid=system/tiger@myorcl tables=(emp) file=d:xx.dmp touser=scott 
      3. 导入表的结构 
        只导入表的结构而不导入数据 
        imp userid=scott/tiger@myorcl tables=(emp) file=d:xx.dmp  rows=n 
      4. 导入数据 
        如果对象(如比表)已经存在可以只导入表的数据 
        imp userid=scott/tiger@myorcl tables=(emp) file=d:xx.dmp  ignore=y 
      导入方案n 
      导入方案是指使用import工具将文件中的对象和数据导入到一个或是多个方案中。如果要导入其它方案,要求该用户具有dba的权限,或者imp_full_database 
      1. 导入自身的方案 
        imp userid=scott/tiger file=d:xxx.dmp 
      2. 导入其它方案 
        要求该用户具有dba的权限 
        imp userid=system/manager file=d:xxx.dmp fromuser=system touser=scott 
        导入数据库n 
        在默认情况下,当导入数据库时,会导入所有对象结构和数据,案例如下: 
        imp userid=system/manager full=y file=d:xxx.dmp
View Code

6.数据字典和动态性能视图

  数据字典:有数据库的系统信息;动态视图:记载了历程启动后的相关信息

 

   数据字典记录了数据库的系统信息,它是只读表和视图的集合,数据字典的所有者为sys用户。
     用户只能在数据字典上执行查询操作(select语句),而其维护和修改是由系统自动完成的。
   这里我们谈谈数据字典的组成:数据字典包括数据字典基表和数据字典视图,其中基表存储数据库的基本信息,普通用户不能直接访问数据字典的基表。数据字典视图是基于数据字典基表所建立的视图,普通用户可以通过查询数据字典视图取得系统信息。数据字典视图主要包括user_xxx,all_xxx,dba_xxx三种类型。

 

    user_tables;n 
    用于显示当前用户所拥有的所有表,它只返回用户所对应方案的所有表
    比如:select table_name from user_tables;
      all_tables;n 
    用于显示当前用户可以访问的所有表,它不仅会返回当前用户方案的所有表,还会返回当前用户可以访问的其它方案的表:
    比如:select table_name from all_tables;
      dba_tables;n 
    它会显示所有方案拥有的数据库表。但是查询这种数据库字典视图,要求用户必须是dba角色或是有select any table系统权限。 

    例如:当用system用户查询数据字典视图dba_tables时,会返回system,sys,scott...方案所对应的数据库表。 

    1)用户名,权限,角色

      dba_users可以显示所有数据库用户的详细信息;
      dba_sys_privs,可以显示用户所具有的系统权限;
      ba_tab_privs,可以显示用户具有的对象权限;
      dba_col_privs可以显示用户具有的列权限;
      dba_role_privs可以显示用户所具有的角色。

    2)表空间

       建立数据表空间
      在建立数据库后,为便于管理表,最好建立自己的表空间
      create tablespace data01 datafile 'd: estdada01.dbf' size 20m uniform size 128k;
      说明:执行完上述命令后,会建立名称为data01的表空间,并为该表空间建立名称为data01.dbf的数据文件,区的大小为128k
      n 使用数据表空间 :create table mypart(deptno number(4), dname varchar2(14), loc varchar2(13)) tablespace data01;  

      使表空间脱机 :alter tablespace 表空间名 offline;
      使表空间联机 :alter tablespace 表空间名 online;
      只读表空间
      当建立表空间时,表空间可以读写,如果不希望在该表空间上执行updatedeleteinsert操作,那么可以将表空间修改为只读
      alter tablespace 表空间名 read only;
      (修改为可写是 alter tablespace 表空间名 read write;)

      删除表空间:drop tablespace ‘表空间’ including contents and datafiles;

      说明:including contents表示删除表空间时,删除该空间的所有数据库对象,而datafiles表示将数据库文件也删除。

      表空间扩展

      1. 增加数据文件
        SQL> alter tablespace sp01 add datafile ‘d: estsp01.dbf’ size 20m;
      2. 增加数据文件的大小
        SQL> alter tablespace 表空间名 ‘d: estsp01.dbf’ resize 20m;
        这里需要注意的是数据文件的大小不要超过500m
      3. 设置文件的自动增长。
        SQL> alter tablespace 表空间名 ‘d: estsp01.dbf’ autoextend on next 10m maxsize 500m; 

7.约束  

  oracle中,约束包括:not null、 unique, primary key, foreign key,和check五种。

  例子:

商店售货系统表设计案例n 
现有一个商店的数据库,记录客户及其购物情况,由下面三个表组成:商品goods(商品号goodsId,商品名 goodsName,单价 unitprice,商品类别category,供应商provider); 
客户customer(客户号customerId,姓名name,住在address,电邮email,性别sex,身份证cardId); 
购买purchase(客户号customerId,商品号goodsId,购买数量nums); 

请用SQL语言完成下列功能: 
1. 建表,在定义中要求声明: 
(1). 每个表的主外键; 
(2). 客户的姓名不能为空值; 
(3). 单价必须大于0,购买数量必须在1到30之间; 
(4). 电邮不能够重复; 
(5). 客户的性别必须是 男 或者 女,默认是男; 

SQL> create table goods(goodsId char(8) primary key, --主键 
            goodsName varchar2(30), 
            unitprice number(10,2) check(unitprice>0), 
            category varchar2(8), 
            provider varchar2(30) 
     ); 
SQL> create table customer( customerId char(8) primary key, --主键 
            name varchar2(50) not null,  --不为空 
            address varchar2(50), 
            email varchar2(50) unique, 
            sex char(2) default '' check(sex in ('''')), -- 一个char能存半个汉字,两位char能存一个汉字 
            cardId char(18) 
     ); 
SQL> create table purchase( customerId char(8) references customer(customerId), 
            goodsId char(8) references goods(goodsId), 
            nums number(10) check (nums between 1 and 30) 
     ); 
表是默认建在SYSTEM表空间的 
View Code

例子2

如果在建表时忘记建立必要的约束,则可以在建表后使用alter table命令为表增加约束。但是要注意:增加not null约束时,需要使用modify选项,而增加其它四种约束使用add选项。 

1. 增加商品名也不能为空 
SQL> alter table goods modify goodsName not null; 
2. 增加身份证也不能重复 
SQL> alter table customer add constraint xxxxxx unique(cardId); 
3. 增加客户的住址只能是’海淀’,’朝阳’,’东城’,’西城’,’通州’,’崇文’,’昌平’; 
SQL> alter table customer add constraint yyyyyy check (address in (’海淀’,’朝阳’,’东城’,’西城’,’通州’,’崇文’,’昌平’)); 
View Code

  1)删除约束

    当不再需要某个约束时,可以删除。

    alter table 表名 drop constraint 约束名称;
    特别说明一下:
    在删除主键约束的时候,可能有错误,比如:
    alter table 表名 drop primary key;
    这是因为如果在两张表存在主从关系,那么在删除主表的主键约束时,必须带上cascade选项 如像:
    alter table 表名 drop primary key cascade; 

  2)显示约束

    A.显示约束信息
      通过查询数据字典视图user_constraints,可以显示当前用户所有的约束的信息。
      select constraint_name, constraint_type, status, validated from user_constraints where table_name = '表名';
    B.显示约束列
      通过查询数据字典视图user_cons_columns,可以显示约束所对应的表列信息。
      select column_name, position from user_cons_columns where constraint_name = '约束名';
    C.当然也有更容易的方法,直接用pl/sql developer查看即可

  3)表级定义 列级定义
    A: 列级定义
      列级定义是在定义列的同时定义约束。
      如果在department表定义主键约束
      create table department4(dept_id number(12) constraint pk_department primary key,
      name varchar2(12), loc varchar2(12));
     B: 表级定义
      表级定义是指在定义了所有列后,再定义约束。这里需要注意:
      not null约束只能在列级上定义。
      以在建立employee2表时定义主键约束和外键约束为例:
      create table employee2(emp_id number(4), name varchar2(15),
      dept_id number(2), constraint pk_employee primary key (emp_id),
      constraint fk_department foreign key (dept_id) references department4(dept_id)); 

------------------------------------休息一下----------------------------------------------------

11.pl/sql分类 -- 过程,函数,包,触发器

  标识规范:变量:v_;常量:c_;游标:_cursor;例外:e_开头的

  1)Pl/sal编程就是块编程

    pl/sql块由三个部分构成:定义部分,执行部分,例外处理部分。 

    如下所示:

declare 
/*定义部分——定义常量、变量、游标、例外、复杂数据类型*/ 
begin 
/*执行部分——要执行的pl/sql语句和sql语句*/ 
exception 
/*例外处理部分——处理运行的各种错误*/ 
end; 
定义部分是从declare开始的,该部分是可选的; 
执行部分是从begin开始的,该部分是必须的; 
例外处理部分是从exception开始的,该部分是可选的。 
可以和java编程结构做一个简单的比较。

例子:

declare  
    --定义变量   
    v_ename varchar2(5);   
    v_sal  number(7,2);   
begin  
    --执行部分   
    select ename,sal into v_ename,v_sal from emp where empno=&aa;   
    --在控制台显示用户名   
dbms_output.put_line('用户名是:'||v_ename||' 工资:'||v_sal);   
    --异常处理   
exception   
when no_data_found then  
    dbms_output.put_line('朋友,你的编号输入有误!');   
end;   
View Code

  2)过程

    例子:

创建:
create or replace procedure sp_pro1 is  
begin--执行部分   
insert into mytest values('韩顺平','m1234');   
end; 
调用
A:exec 过程名(参数值1,参数值2...); 
    B:call 过程名(参数值1,参数值2...);
C:java中如何调用
例子:
import java.sql.*;   
public class TestOraclePro{   
    public static void main(String[] args){   
           
        try{   
            //1.加载驱动   
            Class.forName("oracle.jdbc.driver.OracleDriver");   
            //2.得到连接   
            Connection ct = DriverManager.getConnection("jdbc:oracle:thin@127.0.0.1:1521:MYORA1","scott","m123");   
  
            //3.创建CallableStatement   
            CallableStatement cs = ct.prepareCall("{call sp_pro3(?,?)}");   
            //4.给?赋值   
            cs.setString(1,"SMITH");   
            cs.setInt(2,10);   
            //5.执行   
            cs.execute();   
            //关闭   
            cs.close();   
            ct.close();   
        } catch(Exception e){   
            e.printStackTrace();   
        }   
    }   
}  
View Code  

  3)函数

    函数用于返回特定的数据,当建立函数时,在函数头部必须包含return子句

--输入雇员的姓名,返回该雇员的年薪   
create function annual_incomec(name varchar2)   
return number is  
annual_salazy number(7,2);   
begin  
    --执行部分   
    select sal*12+nvl(comm, 0) into annual_salazy from emp where ename=name;   
    return annual_salazy;   
end;   
/ 
如果函数创建有问题可以show error来查问题
Pl/sql中调用函数
SQLvar income number   
SQL> call annual_incomec('scott') into: income;   
SQL> print income  
同样我们可以在java程序中调用该函数 
    select annual_income('SCOTT') from dual; 
    这样可以通过rs.getInt(l)得到返回的结果。
View Code

  4)包

  逻辑上组合过程和函数,分为包规范包体两部分

创建包:
a.--创建一个包sp_package 
    b--声明该包有一个过程update_sal 
    c--声明该包有一个函数annual_income 
Sql代码:
create package sp_package is  
  procedure update_sal(name varchar2, newsal number);   
  function annual_income(name varchar2) return number;   
end;  
包的规范只包含了过程和函数的说明,但是没有过程和函数的实现代码。包体用于实现包规范中的过程和函数。 
    创建包体的Sql代码
create or replace package body sp_package is  
  procedure update_sal(name varchar2, newsal number)    
  is  
  begin    
    update emp set sal = newsal where ename = name;   
  end;   
  function annual_income(name varchar2) return number is  
    annual_salary number;   
  begin  
    select sal * 12 + nvl(comm, 0) into annual_salary from emp   
     where ename = name;   
    return annual_salary;   
  end;   
end;   
/  
调用包:都是调用包的成员call sp_package.update_sal('SCOTT', 1500); 
View Code

  5)触发器

    常用的触发事件包括insert,update,delete语句,而触发操作实际就是一个pl/sql块。可以使用create trigger来建立触发器

12.定义并使用变量,复合类型 

  标量类型,复合类型,参照类型,lob

 

  标识规范:变量:v_;常量:c_;游标:_cursor;例外:e_开头的

  1)标量类型(scalar)

    定义:name datatype [not null] [:=| default expr]

    其中datatype还可以用数据库表中列类型表示:emp.ename%type

    例子:

例子:定义一个布尔变量,不能为空,初始值为false 
v_valid boolean not null default false;
SQL例子:
declare  
  c_tax_rate number(3,2):=0.03;   
  --用户名   
  v_ename emp.ename%type;   
  v_sal number(7,2);   
  v_tax_sal number(7,2);   
begin  
--执行   
    select ename,sal into v_ename,v_sal from emp where empno=&no;   
--计算所得税   
    v_tax_sal := v_sal*c_tax_rate;   
--输出   
    dbms_output.put_line('姓名是:'||v_ename||'工资:'||v_sal||' 交税:'||v_tax_sal);   
end;   
/  
View Code

  2)复合类型(composite)

    A:类似高级语言中的结构体,调用方式(类型名.成员名)

例子:

type emp_record_type is record(   


    name   emp.ename%type,   


    salary emp.sal%type,   


    title  emp.job%type);   


--定义了一个sp_record变量,这个变量的类型是emp_record_type   


  sp_record emp_record_type;
View Code

    B:类似高级语言中的数组,但是下标没有限制可以为负数

    C:嵌套表(nested table)

    D:变长数组

  3)参照类型(reference)

    游标变量(ref cursor)和对象类型变量(ref obj_type)

A:游标变量
例子:
1.请使用pl/sql编写一个块,可以输入部门号,并显示该部门所有员工姓名和他的工资。 
    2.在1的基础上,如果某个员工的工资低于200元,就添加100元。 
B:对象类型变量
1.SQL
declare  
--定义游标sp_emp_cursor    
    type sp_emp_cursor is ref cursor;   
--定义一个游标变量   
    test_cursor sp_emp_cursor;      
--定义变量   
v_ename emp.ename%type;    
v_sal emp.sal%type;   
begin  
--执行   
--把test_cursor和一个select结合   
open test_cursor for select ename,sal from emp where deptno=&no;   
--循环取出   
loop   
    fetch test_cursor into v_ename,v_sal;   
    --判断是否test_cursor为空   
    exit when test_cursor%notfound;   
    dbms_output.put_line('名字:'||v_ename||' 工资:'||v_sal);   
end loop;   
end;   
/  
View Code

  4)lob(large object)

13.pl/sql的进阶--控制结构(分支,循环,控制)

  1)三种分支语句:if—then,if – then – else,if – then – elsif – then 

  例子:编写一个过程,可以输入一个雇员名,如果该雇员的工资低于2000,就给该员工工资增加10%

create or replace procedure sp_pro6(spName varchar2) is  
--定义   
v_sal emp.sal%type;   
begin  
    --执行   
    select sal into v_sal from emp where ename=spName;   
    --判断   
    if v_sal<2000 then  
        update emp set sal=sal+sal*10where ename=spName;   
    end if;   
end;   
View Code

  2)循环

    A:loop循环语句以loop开头,以end loop结尾

例子:案例:现有一张表users,表结构如下:
用户id | 用户名
          |
请编写一个过程,可以输入用户名,并循环添加10个用户到users表中,用户编号从1开始增加。

create or replace procedure sp_pro6(spName varchar2) is  
--定义  :=表示赋值   
    v_num number:=1;       
begin  
    loop   
        insert into users values(v_num,spName);   
        --判断是否要退出循环   
        exit when v_num=10;   
        --自增   
        v_num:=v_num+1;   
    end loop;   
end;   
/  
View Code

    B:while

    循环以while...loop开始,以end loop结束

例子:

案例:现有一张表users,表结构如下:
用户id 用户名
问题:请编写一个过程,可以输入用户名,并循环添加10个用户到users表中,用户编号从11开始增加。

SQL:
create or replace procedure sp_pro6(spName varchar2) is  
--定义  :=表示赋值   
    v_num number:=11;       
begin  
    while v_num<=20 loop   
    --执行   
       insert into users values(v_num,spName);   
       v_num:=v_num+1;   
    end loop;   
end;   
/   
View Code

    C:for循环

例子:
begin  
  for i in reverse 1..10 loop   
    insert into users values (i, 'shunping');   
  end loop;   
end; 
View Code

end; 

     D:顺序控制语句goto,null

      Goto:

      基本语法如下 goto lable,其中lable是已经定义好的标号名    

例子:
declare  
  i int := 1;   
begin  
  loop   
    dbms_output.put_line('输出i=' || i);   
    if i = 1{} then  
      goto end_loop;   
    end if;   
    i := i + 1;   
  end loop;   
  <<end_loop>>   
  dbms_output.put_line('循环结束');   
end; 
View Code

      Null:类似于高级语句中的continue:直接将控制传递到下一条语句

例子:
declare  
  v_sal   emp.sal%type;   
  v_ename emp.ename%type;   
begin  
  select ename, sal into v_ename, v_sal from emp where empno = &no;   
  if v_sal < 3000 then  
    update emp set comm = sal * 0.1 where ename = v_ename;   
  else  
    null;   
  end if;   
end; 
View Code

 ------------------------------------休息一下----------------------------------------------------

14.PL/SQL分页

  一步一步来

  1)有返回值的存储过程完整例子(列表[结果集])

例子:编写一个过程,输入部门号,返回该部门所有雇员信息。

分析: 由于oracle存储过程没有返回值,它的所有返回值都是通过out参数来替代的,列表同样也不例外,但由于是集合,所以不能用一般的参数,必须要用pagkage了。所以要分两部分:
A:创建一个包,在这个包中定义类型test_cursor游标
create or replace package testpackage as  
  TYPE test_cursor is ref cursor;   
end testpackage;
B:创建存储过程
create or replace procedure sp_pro9(spNo in number,p_cursor out testpackage.test_cursor) is  
begin  
  open p_cursor for  
    select * from emp where deptno = spNo;   
end sp_pro9;  

最后在java中调用这个存储过程
try{   
            //1.加载驱动   
            Class.forName("oracle.jdbc.driver.OracleDriver");   
            //2.得到连接   
            Connection ct = DriverManager.getConnection("jdbc:oracle:thin@127.0.0.1:1521:MYORA1","scott","m123");   
  
            //看看如何调用有返回值的过程   
            //3.创建CallableStatement   
            /*CallableStatement cs = ct.prepareCall("{call sp_pro9(?,?)}");   
  
            //4.给第?赋值   
            cs.setInt(1,10);   
            //给第二个?赋值   
            cs.registerOutParameter(2,oracle.jdbc.OracleTypes.CURSOR);   
  
            //5.执行   
            cs.execute();      
            //得到结果集   
            ResultSet rs=(ResultSet)cs.getObject(2);        
            while(rs.next()){   
                System.out.println(rs.getInt(1)+" "+rs.getString(2));   
            }    
        } catch(Exception e){   
            e.printStackTrace();   
        } finally{   
            //6.关闭各个打开的资源   
            cs.close();   
            ct.close();   
        }   
View Code

  2)编写分页过程

Sql代码:
select * from  
  (select t1.*, rownum rn from (select * from emp) t1 where rownum<=10)   
where rn>=6
开发一个包写存储过程
create or replace package testpackage as  
  TYPE test_cursor is ref cursor;   
end testpackage; 
View Code

开始编写分页的过程

create or replace package testpackage as  
  TYPE test_cursor is ref cursor;   
end testpackage;   
--开始编写分页的过程   
create or replace procedure fenye   
    (tableName in varchar2,   
     Pagesize in number,--一页显示记录数   
     pageNow in number,   
     myrows out number,--总记录数   
     myPageCount out number,--总页数   
     p_cursor out testpackage.test_cursor--返回的记录集   
    ) is  
--定义部分   
--定义sql语句 字符串   
v_sql varchar2(1000);   
--定义两个整数   
v_begin number:=(pageNow-1)*Pagesize+1;   
v_end number:=pageNow*Pagesize;   
begin  
--执行部分   
v_sql:='select * from (select t1.*, rownum rn from (select * from '||tableName||') t1 where rownum<='||v_end||') where rn>='||v_begin;   
--把游标和sql关联   
open p_cursor for v_sql;   
--计算myrows和myPageCount   
--组织一个sql语句   
v_sql:='select count(*) from '||tableName;   
--执行sql,并把返回的值,赋给myrows;   
execute inmediate v_sql into myrows;   
--计算myPageCount   
--if myrows%Pagesize=0 then这样写是错的   
if mod(myrows,Pagesize)=0 then  
  myPageCount:=myrows/Pagesize;   
else  
  myPageCount:=myrows/Pagesize+1   
end if;   
--关闭游标   
close p_cursor;   
end;   
/  
View Code

java测试 

try{   
            //1.加载驱动   
            Class.forName("oracle.jdbc.driver.OracleDriver");   
            //2.得到连接   
            Connection ct = DriverManager.getConnection("jdbc:oracle:thin@127.0.0.1:1521:MYORA1","scott","m123");   
  
            //3.创建CallableStatement   
            CallableStatement cs = ct.prepareCall("{call fenye(?,?,?,?,?,?)}");   
  
            //4.给第?赋值   
            cs.seString(1,"emp");   
            cs.setInt(2,5);   
            cs.setInt(3,2);   
  
            //注册总记录数   
            cs.registerOutParameter(4,oracle.jdbc.OracleTypes.INTEGER);   
            //注册总页数   
            cs.registerOutParameter(5,oracle.jdbc.OracleTypes.INTEGER);   
            //注册返回的结果集   
            cs.registerOutParameter(6,oracle.jdbc.OracleTypes.CURSOR);   
  
            //5.执行   
            cs.execute();    
  
            //取出总记录数   /这里要注意,getInt(4)中4,是由该参数的位置决定的   
            int rowNum=cs.getInt(4);   
  
            int pageCount = cs.getInt(5);               
            ResultSet rs=(ResultSet)cs.getObject(6);    
  
            //显示一下,看看对不对     
            System.out.println("rowNum="+rowNum);   
            System.out.println("总页数="+pageCount);   
     
            while(rs.next()){   
                System.out.println("编号:"+rs.getInt(1)+" 名字:"+rs.getString(2)+" 工资:"+rs.getFloat(6));   
            }    
        } catch(Exception e){   
            e.printStackTrace();   
        } finally{   
            //6.关闭各个打开的资源   
            cs.close();   
            ct.close();   
        }   
运行,控制台输出: 
rowNum=19 
总页数:4 
编号:7369 名字:SMITH 工资:2850.0 
编号:7499 名字:ALLEN 工资:2450.0 
编号:7521 名字:WARD 工资:1562.0 
编号:7566 名字:JONES 工资:7200.0 
编号:7654 名字:MARTIN 工资:1500.0 
View Code

 

15.例外处理

 

  例外分为预定义例外,非预定义例外和自定义例外三种

  预定义例外用于处理常见的oracle错误 

  非预定义例外用于处理预定义例外不能处理的例外
  自定义例外用于处理与oracle错误无关的其它情况 

  1)预定义例外

    预定义例外有20多个预定义例外

    1.case_not_found:when子句中没有包含必须的条件分支发生例外

    2.cursor_already_open:重新打开已经打开的游标时,会隐含的触发

    3.dup_val_on_index:在唯一索引所对应的列上插入重复的值

    4.invalid_cursor:当试图在不合法的游标上执行操作时

    5.invalid_number:输入的数据有误时

    6. no_data_found :当执行select into 没有返回行

    7.too_many_rows:当执行select into语句时,返回超过了一行

    8.zero_divide:执行2/0语句时,则会触发该例外

    9.value_error:执行赋值操作时,变量的长度不足以容纳实际数据

    10.其他预定义例外是出现在pl/sql中的而不是oracle中发生的

        Login_denied:用户非法登录

        Not_logged_on:没有用户登录执行dml操作

        Storage_error:超过内存空间

        Timeout_on_resource:等待资源超时

--定义
V_name emp.ename%type;
Begin
--
Select ename into v_ename from emp where empno=%gno;
Dbms_output.put_line(‘名字:’||v_ename)
Exception
When no_data_found then
Dbms_output.putline(‘编号没有!’);
/
执行输入一个不存在的编号,回显:编号没有!
View Code

  2)非预定义例外

    比如在pl/sql块中执行dml语句时,违反了约束规定等等很少有这样的例外

  3)自定义例外

    自定义例外与oracle错误没有任何关联,它是由开发人员为特定情况所定义的例外

    例子:请编写一个pl/sql块,接收一个雇员的编号,并给该雇员工资增加1000元,如果该雇员不存在,请提示。

自定义例外 
create or replace procedure ex_test(spNo number)   
is  
--定义一个例外   
myex exception;   
begin  
--更新用户sal   
update emp set sal=sal+1000 where empno=spNo;   
--sql%notfound这是表示没有update   
--raise myex;触发myex   
if sql%notfound then  
raise myex;   
end if;   
exception   
when myex then  
dbms_output.put_line('没有更新任何用户');   
end;   
/  --自定义例外create or replace procedure ex_test(spNo number)is
测试
SQL> exec ex_test(56); 
View Code

没有更新任何用户

 

16 oracle的视图 

  1)视图与表的区别n 
    表需要占用磁盘空间,视图不需要
    视图不能添加索引(所以查询速度略微慢点)
    使用视图可以简化,复杂查询
    比如:学生选课系统
      视图的使用利于提高安全性
    比如:不同用户查看不同视图

 

  2)创建修改视图

 

    创建视图:create view 视图名 as select 语句[with read only]

 

    创建或修改视图:create or replace view 视图名 as select 语句[with read only]

 

    删除视图:drop view 视图名

 

    当表结构复杂的时候我们可以用视图!

 

  例子为简化操作,用一个视图解决 显示雇员编号,姓名和部门名称

 

Sql代码

 

create view myview2 as select emp.empno,emp.ename,dept.dname from emp,dept where emp.deptno=dept.deptno;  

 

create view myview2 as select emp.empno,emp.ename,dept.dname from emp,dept where emp.deptno=dept.deptno;

 

视图之间也可以做联合查

17.查询优化

  1)尽量用EXISTS代替IN操作

  2)用NOT EXISTS 或者外链接代替NOT IN

    因为NOT IN 不能应用表索引

  3)尽量不用“<>”或者!=

  

QTH1`7Z$)T_8}K64Z)9L{_L

原文地址:https://www.cnblogs.com/xiaoping1993/p/oracle.html