首页 > 代码库 > oracle笔记

oracle笔记

一、sql*plus常用命令

     (1)connect

     用法:conn 用户名/密码@网络服务名[as sysdba/sysoper]

     当特权用户连接时,必须带上as sysdba或是as sysoper

     (2)disc[onnect]

     说明:该命令用来断开与当前数据库的连接

     (3)passw[ord]

     说明:该命令用于修改用户的密码,如果想修改其他用户的密码需要用sys/system登录

     (4)show user

     说明:显示当前用户名

     (5)exit

     说明:该命令会断开与数据库的连接,同时会退出sql*plus

二、文件操作命令

     (1)start和@

     说明:运行sql脚本

     案例:sql>@ d:\a.sql 或者sql>START d:\a.sql

     (3)edit

     说明该命令可以编辑指定的sql脚本

     案例:sql>edit d:\a.sql

     (4)spool

     说明:该命令可以将sql*plus屏幕上的内容输出到指定文件中去

     案例:sql>spool d:\b.sql 并输入sql>spool off

三、交互式命令

     (1)&

     说明:可以替代变量,而该变量在执行时,需要用户输入。

     sql>select * from emp where job=‘&job‘

     sql>desc 表名(用来显示表的结构)

四、显示和设置环境变量

     概述:可以用来控制输出的各种格式,set show 如果

     永久的保存相关的设置,可以修改glogin.sql脚本

     (1)linesize

     说明:设置显示行的宽度,默认是80个字符

     sql>show linesize

     sql>set linesize 90

     (2)pagesize

     说明:设置每页显示的行数目,默认是14

     用法和Linesize一样

     oracle用户的管理

     (1)创建用户:

     概述:在oracle中要创建一个新的用户使用create user

     语句,一般是具有dba(数据库管理员)的权限才能使用。

     sql>create user lxl identified by lxl;

     (2)给用户修改密码

     概述:如果给自己修改密码可以直接使用

     sql>password 用户名

     如果给别人修改密码需要具有dba的权限,或是用于alter user的系统权限

     sql>alter user 用户名 identified by 新密码

     (3)删除用户

     概述:一般以dba的身份去删除某个用户,如果用其他用户去删出则需要具有drop user的权限

     比如sql>drop user 用户名[casecade]

     在删除用户时,注意如果删除的用户,已经创建了表,那么就需要

     在删除时带一个参数cascade(级联)

     创建的新用户是没有任何权限的,甚至连登陆的

     数据库的权限都没有,需要为其制定相应的权限。给一个用户赋权限使用命令grant,回收权限使用命令revoke

 sql>grant connect to lxl

权限:指执行特定类型sql命令或是访问其它方案对象的权利

①      系统权限:指执行特定类型sql命令的权利。它用于控制用户可以执行的一个或是一组数据库操作。比如比如用户具有createtable权限时,可以在其方案中建表,当用户具有create any table 权限时,可以在任何方案中建表。常用的有:

Create session  连接数据库 create table 建表

Create view 建视图 create public synonym 建同义词

Create procedure 建过程、函数 create trigger 建触发器

Create cluser 建簇

授予系统权限

授予系统权限是由dba完成的,如果用其他用户来授予系统权限,则要求该用户必须具有with any privilege的系统权限在授予系统权限时,可以带有with admin option选项,这样,被授予权限的用户或是角色还可以将该系统权限授予其它的用户或是角色。

Sql>grant create session,crerate table to lxl with admin option;

Sql>grant create view to lxl;

回收系统权限:

一般情况下,回收系统权限时dba来完成的,如果其它的用户来回收系统权限,要求该用户必须具有相应系统权限及转授系统权限的选项(with admin option)。回收系统权限使用revoke来完成。当回收了系统权限后,用户就不能执行相应的操作了【系统权限不是级联回收的】

②      对象权限(select、 insert、 update、 delete、 all、 create index、references(引用)、execute(执行)......):访问其它方案对象的权利,用户可以直接访问自己方案的对象,但是如果要访问别的方案的对象,则必须具有对象的权限。     

              sql>grant select on emp to lxl

              sql>revoke select on emp from lxl(回收权限)

     角色:①自定义角色:自己写一个角色包括多个不同权限

               ②预定义角色:事先已经存在的角色

     方案:oracle数据库对数据对象的组织的方式是以用户人为单位组织的。

创建用户时,那么oracle数据库会自动给用户一个方案,方案包括各种各样的数据对象,用户登录后创建的对象都归用户所有,而存在在方案中

     //对权限的维护

     .希望lxl的用户可以去查询scott的emp表/还希望lxl可以把这个权限继续给别人

     --如果是对象权限的,加入with grant option(权限回收时传递的权限也会被回收,即级联)但要注意with grant option选项能被授予角色

sql>grant select on emp to lxl with grant option;

--如果是系统权限

system给lxl权限:就加入with admin option

sql>grant select on scott.emp to lxl with admin option

授予列权限:(以Scott用户登录)

Sql>grant update on emp(sal) to lxl;

建立角色(不验证)

Sql>create role 角色名 not identified;

建立角色(数据库验证)

Sql>create role 角色名 identified by lixiaolong

角色授权

 注意:系统权限的unlimited tablespace和对象权限的with grant option选项是不能授予角色的。

Sql>conn system/li1127593600;

Sql>grant create session to 角色名 with admin option;

Sql>grant select on scott.emp to 角色名

Sql>grant insert,update,delete on scott.emp to角色名;

删除角色

由dba来执行或具有drop any role 系统权限

Sql>drop role 角色名;

显示角色信息

  1. 显示所有角色

Sql>select * from dba_roles;

  1. 显示角色具有的系统权限

Sql>select privilege,admin_option from role_sys_privs where role=’角色名’;

  1. 显示角色具有的对象权限

查看数据字典视图dba_tab_privs可以查看角色具有的对象权限或是列的权限。

  1. 显示用户具有的角色,及默认角色

当以用户身份连接到数据库时,oracle会自动的激活默认的角色,通过查询数据字典视图dba_role_privs可以显示某个用户具有的所有角色及当前默认的角色

Sql>select granted_role,default_role from dba_role_privs where grantee=’角色名’;

五、使用profile管理用户口令

      概述:profile是口令机制。资源限制的命令集合,当建立数据库时,

     oracle会自动建立名称为default的profile。当建立用户没有指定profile选项

     ,那oracle就会自动将default分配给用户

     (1)账号锁定

     概述:指定该用户(账户)登录时最多可以输入密码的次数,也可以指定用户锁定的时间(天)一般用

     dba的身份去执行该命令

     例子:指定该账号(用户)登录时最多只能尝试3次登录,锁定时间为2天,

            sql>create profile lock_account limit

            filed_login_attempts 3 password_lock_time 2;

            sql>alter user lxl profile lock_account;

     (2)给账户(用户)解锁

              sql>alter user lxl account unlock;

     (3)终止口令

     为了让用户定期修改密码可以使用终止口令

     的指令来完成,同样这个命令也需要dba身份来操作

     例子:给前面创建的用户lxl创建一个profile文件,要求该用户每

     隔10天要修改自加的登录密码,宽限期为2天。

     sql>create profile myprofile limit password_life_time 10 password_grace_tieme 2;

     sql>alter user lxl profile myprofile    

六、口令历史

     概述:如果希望用户在修改密码时,不能使用以前使用过的密码

     ,可使用口令历史,这样oracle就会将口令修改的信息存放在数据字典中

     ,这样当用户修改密码时,oracle就会对新旧密码进行比较,当发现新旧密码一样

     时,就提示用户重新输入密码。

     例子:

         1)建立profile

         sql>create profile password_history limit password_life_time 10 password_grace_time 2 password_reuse_time 10;

         password_reuse_time//指口令可重时间即10天后就可以重用

         2)分配给用户

         sql>alter user lxl profile password_history;

         3)删除profile

         概述:当不需要某个profile文件时,可以删除文件

         sql>drop profile password_histor[casecade(级联)]

oracle表的管理

oracle支持的数据类型

例子:char(10)‘小韩‘前四个字符放‘小韩‘,后添6个空格不全(char的查询效率很高)

varchar2(20) 变长 最大字符4000字符(节省空间)

clob()字符型大对象最大4G

数字型

number 范围 10的-38次方-10的38次方

number(5,2)表示一个小数有5位有效数,2位小数。范围:-999.99-999.99

number(5)表示5位整数范围-99999-99999

date 包含年月日合时分秒

blob 图片 二进制数据 可以存放图片/声音 4G

添加一个字段

sql>alter table student add(classid number(2));

修改字段的长度

sql>alter table student modify (xm varchar2(30));

修改字段的类型/或是名字(不能能有数据)

sql>alter table student modify (xm char(30));

删除一个字段

sql>alter table student drop column sal;

修改表的名字

sql>rename student to stu;

删除表

sql>drop table student;

添加数据

所有字段都插入

sql>insert into student values(‘A001‘,‘张三‘,‘男‘,‘01-5月-05‘,10);

oracle中默认的日期格式‘DD-MON-YY‘ dd日子(天)mon 月份 yy 2位的年 ‘06-6月-99‘ 1999年6月9号

改日期的默认格式

sql>alter session set nls_date_format=‘yyyy-mm-dd‘;

修改后,可以用我们熟悉的格式添加日期类型:

sql>insert into student vlaues(‘A002‘,‘MIKE‘,‘男‘,‘1903-05-09‘,10);

插入部分字段:

sql>insert into student(xh,xm,sex)values(‘A003‘,‘JOHN‘,‘女‘);

插入空值

sql>insert into student(xh,xm,sex,birthday)values(‘A004‘,‘MARTIN‘,‘男‘,null);

查询空值

sql>select * from student where birthday is null;

修改一个字段

update student set sex=‘女‘ where xh=‘A001‘;

删除数据

sql>delete from student;

删除所有记录,表结构还在,写日志,可以恢复(利用回滚rollback)

删之前:sql>savepointe a;(设置保存点)

删之后:sql>rollback to a;(回滚到保存点)

sql>drop table student;删除表的结构和数据

sql>delete from student where xh=‘A001‘;删除一个记录

sql>truncate table student;删除表中的所有记录,表结构还在,不写日志,无法找回删除的记录,速度快

查看表的结构

sql>desc student;

查询所有列

sql>select * from student;

查询指定列

sql>select xh,sex from student;

如何取消重复行

sql>select distinct xm from student;

打开显示操作执行的时间

sql>set timing on;

①使用算数表达式

②使用列的别名

sql>select ename "姓名" ,sal*12 as "年收入" from emp;

③如何处理null值

④使用nvl函数处理null值(如果sal为空用0代替)

sql>select ename "姓名" ,nvl(sal,0)*12 as "年收入" from emp;

⑤如何连接字符串(||)

select ename || ‘is a ‘|| job from emp;

⑥使用where字句

大于某个出生年龄

sql>select ename,hiredate from emp where hiredate>‘1-1月-1982‘;

⑦使用like字符

%:表示任意0到多个字符 _表示单个字符

⑧在where条件中使用in

⑨使用is null的操作符

使用逻辑操作符号

使用order by字句(asc升序(默认)  desc降序)

使用列的别名排序

sql>select ename,sal*12 "年薪" from emp order by "年薪" asc;

复杂查询

不是单组分组函数:

原因:

1,  如果程序中使用了分组函数,则有两种情况可以

使用:程序中存在group by,并指定了分组条件,这样可以将分组条件一

起查询出来改为:select deptno,count(empno) from emp group by deptno;

如果不使用分组的活,则只能单独使用分组函数改为:select count(empno) from emp;

2,  在使用分组函数的时候,不能出现分组条件之外的字段

总结:在select需要查询的语句中选中的字段,必须出现在group by子句中,除了分组函数的参数。

查询表的薪水最高值和最低值

sql>select max(sal),min(sal) from emp;

查询表的薪水最高值对应姓名

sql>select ename,sal from emp where sal=(select max(sal) from emp);

查询表的薪水大于平均薪水员工的信息

sql>select * from emp where sal>(select avg(sal) from emp);

group by 和having字句(分组字段的名字必须出现在select查询的选择列里面)

group by用于对查询的结果分组统计

sql>select avg(sal),max(sal) from emp group by deptno;

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

sql>select  avg(sal),max(sal),deptno,job from emp group by deptno,job;

having字句用于限制分组显示结果

显示平均工资低于2000的部门号和它的平均工资

sql>select avg(sal),max(sal),deptno from emp group by deptno having avg(sal)>2000

总结:

1.分组函数只能出现在选择select列表、having、order by字句中

2.如果在select语句中同时包含group by,having,order by 那么他们的顺序

是group by,having,order by

3.在选择列中如果有列、表达式、和分组函数,那么这些列

和表达式必须有一个出现在group by字句中,否则就会出错

多表查询(查询条件不能小于表的个数-1)

sql>select a1.ename,a1.sal,a2.dname from emp a1,dept a2 where a1.deptno=a2.deptno;

显示部门号为10的部门名、员工名和工资

sql>select a1.dname,a2.ename,a2.sal from dept a1,emp a2 where a1.deptno=a2.deptno and a1.deptno=10;

显示各个员工的姓名、工资、及其工资的级别

sql>select a1.ename,a1.sal,a2.grade from emp a1,salgrade a2 where a1.sal between a2.losal and a2.hisal;

 自连接

自连接是指在同一张表的连接查询

显示某个员工的上级领导的姓名

sql>select worker.ename,boss.ename from emp worker,emp boss where worker.mgr=boss.empno;

子查询

子查询是指嵌入在其他sql语句中的select语句,也叫嵌套查询

单行子查询

单行子查询是指返回一行数据的子查询语句

显示与SMITH同一个部门的所有员工(数据库在执行sql语句是从右到左扫描,优化条件最好写在右边)

sql>select * from emp where deptno=(select deptno from emp where ename=‘SMITH‘);

多行子查询

多行子查询指返回多行数据的子查询

显示部门号为10的工作相同的雇员的名字、岗位、工资、部门号

sql>select * from emp where job in (select distinct job from emp where deptno=10);

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

显示工资比部门号为30的所有员工的工资高的员工的姓名、工资、和部门号

select ename,sal,deptno from emp where sal>all(select sal from emp where deptno=30);

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

显示工资比部门30的任意一个员工的工资高的员工的姓名、工资、和部门号

select ename,sal,dept from emp where sal>any(select sal from emp where deptno=30);

多列子查询

显示与smith的部门和岗位完全相同的所有雇员

sql>select * from emp where (deptno,job)=select deptno,job from emp where ename=‘SMITH‘;

在from字句中使用子查询

当在from字句中使用子查询时,该子查询会被当作

一个视图来对待,因此也叫作内嵌视图,当在

from子句中使用子查询时,必须给子查询指定别名

显示高于自己部门平均工资的员工的信息

sql>select deptno avg(sal) from emp group by deptno(当作一个子表)

sql>select * from emp a2, (select deptno avg(sal) mysal from emp group by deptno) a1 where a1.deptno=a2.deptno and a2.sal>a1.mysal

分页查询

rownum是oracle分配的

1.rownum分页

(select * from emp)

2.显示rownum[oracle分配的]

sql>select a1.*,rownum rn from (select * from emp) al;

sql>select * from (select a1.*,rownum rn from (select ename,sal from emp order by sal desc) a1 where rownum<=9)where rn>=4;

3.几个查询变化

a.指定查询列,只需修改最里层的子查询

b.如何排序

用查询结果创建新表

这个命令是一个快捷的建表方法。

sql>create table mytable(id,name,sal,job,deptno) as select emptno,ename,sal,job,deptno from emp;

合并查询

为了合并多个select语句的结果可以使用集合操作符号union,union all,intersect,minus

1)union该操作符用于取得两个结果集的并集。当使用该操作符时,会自动去掉结果集中重复行

sql>select ename,sal,job from emp where sal>2500 union select ename,sal,job from emp where job=‘manager‘;

2)union all 不会取消重复行而且不会排序

3)合并查询

intersect 使用该操作符用于取得两个结果集的交集

minus 使用该操作符用于取得两个结果集的差集(谁在前面谁作被减数)

创建数据库有两种方法:

1)通过oracle提供的向导工具(database configure assistant)dbca[数据库配置助手]

2)我们可以用手工步骤直接连接

技巧:

1.使用values子句时,一次能插入一行数据,当使用子查询插入数据时,一条

insert语句可以插入大量的数据。当处理行迁移或者装载外部表的数据到数据库时,可以使用子查询来插入数据

2.使用update语句更新数据时,既可以使用表达式或者数值直接修改数据,也可以使用子查询修改数据

sql>update emp set (job,sal,comm)=(select job,sal,comm from emp where ename=‘SMITH‘)where ename=‘SCOTT‘;

事务

事务用于保证数据的一致性,它由一组相关的dml语句组成,该组的dml语句要么全部成功要么全部失败。

事务和锁

当执行事务操作时(dml语句),oracle会在被作用的表上加锁,防止其他用户改表表的结构。

提交事务

当执行commit语句时可以提交事务,当执行commit语句后,会确认事务的变化,结束事务、删除保存点、

释放锁,当使用commit语句结束事务后,其他会话将可以查到事务变化后的新数据

回退事务

(首先得保证事务没有提交)保存点(savepoint):用于取消部分事务,当结束事务时,会自动的删除该事务所定义的所有保存点。

当执行rollback时,通过指定保存点可以回退到指定的点

取消全部事务:

sql>rollback

只读事务是指只运行执行查询的操作,而不允许执行任何其他dml操作的事务,使用只读事务可以确保用户只能取得某时间点的数据。

设置只读事务

set transaction read only

函数

lower(char):将字符串转化为小写的格式

upper(char):将字符串转化为大写的格式

length(char):返回字符串的长度

substr(char):取字符串的子串

replace(char,search_string,replace_string)

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

round(n,[m])执行四舍五入,如果省掉m,则四舍五入到正数,如果m是正数,则四舍五入到小数点的m位后。如果m是负数,则四舍五入到小数点的m位前

trunc(n,[m])该函数用于截取数字,如果省掉m,就截去小数部分,如果m是正数就截取到小数点的m位后,如果m是负数,则截取到小数点的前m位

mod(m,n)

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

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

日期函数

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

1)sysdate:该函数返回系统时间

2)add_months(d,n)从d日期加上n月

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

转换函数

用于数据类型从一种转为另外一种。oracle可以隐形的转换数据类型

to_char转换字符串

日期转换:(允许yy、yyyy、mm、dd单独显示)

yy:两位数字的月份2004-->04

yyyy:四位数字的年份 2004年

mm:两位数字的月份 8月-->08

dd:2位数字的天 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_date

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

sys_context

1)terminal:当前会话客户所对应的终端的标识符

2)lanuage:语言

3)db_name:当前数据库名称

4)nls_date_format:当前会话客户所对应的日期格式

5)session_user:当前会话客户所对应的数据库用户名

6)current_schema:当前会话客户所对应的默认方案名(一个用户对应一个方案,方案名与用户名相同,方案里有很多数据对象如:表、视图、存储过程、函数、触发器等待)

7)host:返回数据库所在主机的名称

sql>select sys_context(‘userenv‘,‘db_name‘) from dual;

(七)数据库管理

sys和system的区别:

system是数据库内置的一个普通管理员,你手工创建的任何用户在被授予dba角色后都跟这个用户差不多。
sys用数据库的超级用户,数据库内很多重要的东西(数据字典表、内置包、静态数据字典视图等)都属于这个用户,sys用户必须以sysdba身份登录。

sysdba和sysoper的区别:

dba权限的用户

dba用户是指具有dba角色的数据库用户。特权用户可以执行启动实例,

关闭实例等特殊操作,而dba用户只有在启动数据库后才能执行各种管理工作

sysdba>sysoper>dba

管理初始化参数

初始化参数用于设置实例或是数据库的特征。

显示初始化参数

sql>showparameter;

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

逻辑备份是指使用工具export将数据对象的结构和和数据导出到文件的过程,逻辑恢复是指当数据库对象被误操作而损坏后使用工具import利用备份的文件把数据对象导入到数据库的过程。

物理备份即指可再数据库open的状态下进行也可以在数据库后进行,但是逻辑备份和恢复只能在open的状态下进行。导出

导出具体的分为:导出表,导出方案,导出数据库三种方式

导出使用exp命令来完成,该命令常用的选项有:

userid:用于执行导出操作的用户名,口令,连接字符串

tables:用于指定执行导出操作的表

owner:用于指定执行导出操作的方案

full=y:用于指定执行导出操作的数据库

inctype:用于指定执行导出操作的增量类型

rows:用于指定执行导出操作是否要导出表中的数据

file:用于指定导出文件名

特别说明:

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

导出表

(1)导出自己的表

expuserid=scott/li1127593600@orcl tables=(emp) file=d:\e1.dmp

(2)导出其它方案的表

如果用户要导出其它方案的表,则需要dba的权限或是

exp_full_database的权限,比如system就可以导出Scott的表

expuserid=system/li1127593600@orcl tables=(scott.emp) file=d:\e2.dmp

3)导出表的结构

exp userid=scott/li1127593600@orcltables file=d:\e3.dmp rows=n;

4)使用直接导出方式

expuserid=scott/li1127593600@orcl tables =(emp) file=e4.dmp direct=y(这种方式比默认的常规方式速度要快)

导出方案

导出方案是指使用export工具导出一个方案或是多个方案中的所有对象(表,索引,约束..)和数据,并放到文件中.

1)导出自己的方案

expscott/li1127593600@orcl owner=scott file=d:\scott.dmp

2)导出其它方案

如果用户要导出其它方案,则需要dba的权限或是

exp_full_database的权限,例如system用户就可以导出任何方案

expsystem/li1127593600@orcl owner(system,scott) file=d:\system.dmp

导出数据库

导出数据库是指利用export导出所有数据库中的对象及数据,

要求该用户具有dba的权限或是exp_full_database权限

expuserid=system/manager@orcl full=y inctype=complete file=x.dmp

导入

导入使用工具import 将文件中的对象和数据导入到数据库中,但是导入要使用的文件必须是

export所导出的文件。与导出相似,导入也分为导入表,导入方案,导入数据库

userid:用于执行导入操作的用户名,口令,连接字符串

tables:用于指定执行导入操作的表

formuser:用于指定源用户

touser:用于指定目标用户

full=y:用于指定执行导入操作的数据库

inctype:用于指定执行导入操作的增量类型

rows:用于指定执行导入操作是否要导出表中的数据

file:用于指定导出文件名

ignore:如果表存在,则只导入数据

导入表

1)导入自己的表

impuserid=scott/li1127593600@orcl tables(emp) file=d:\xx.dmp

2)导入表到其他用户

需要dba的权限或是exp_full_database的权限

impuserid=system/li1127593600@orcl tables(emp) file=d:\xx.dmp touser=scott;

3)导入表的结构

指导人表的结构而不导入数据

impuserid=scott/li1127593600@orcl tables=(emp) file=d:\xx.dmp rows=n;

4)导入数据

如果对象(如此表)已经存在可以只导入表的结构

impuserid=scott/li1127593600@orcl tables(emp) file=d:\xx.dmp ignore=y;

导入方案

是指使用import工具将文件中的对象和数据导入到一个或多个方案中

需要dba的权限或是exp_full_database的权限

1)导入自身的方案

impuserid=scott/li1127593600 file=d:xxx.dmp;

2)导入其他方案

要求用户具有dba的权限

sql>impuserid=system/li1127593600 file=d:\xx.dmp fromuser=system touser=scott;

导入数据库

在默认情况下,当导入数据库时,会导入所有对象结构和数据

impuserid=system/li1127593600 full=y file=d:\xxx.dmp;

数据字典和动态性能视图

数据字典提供了系统信息,它是只读表和视图的集合,数据字典的所有者为sys用户。用户只能在数据字典执行查询操作,而其他维护和修改由系统自动完成。

数据字典的组成:

数据字典包括数据字典基表和数据字典视图,其中基表存储数据库的基本信息,普通用户不能直接访问数据字典的基表。数据字典视图是基于数据字典基表所建立的视图,普通用户可以通过查询数据字典视图取得系统信息。数据字典视图主要包括:user_xxx,all_xxx,dba_xxx三种类型

动态性能视图记载了例程启动后的相关信息。

user_tables

用于显示当前用户所有者的所有表,它只返回用户所对应方案的所有表

比如 :selecttable_name from user_tables;

all_tables:

用于显示当前用户可以访问的所有表,它不仅会返回当前用户方案的所有表,还会

返回当前用户可以访问的其他方案的表

比如:select table_namefrom all_tables;

dba_tables:

它会显示所有方案用于的数据库表,但是查询这种数据字典视图,要求用户必须是dba角色或是有select any table系统权限

用户名,权限,角色

查询oracle中所有的系统权限,一般是dba

sql>select *from system_privilege_map order by name;

查询oracle中所有的角色,一般是dba

sql>select *from dba_roles;

查询oracle中所有对象权限,一般是dba

sql>selectdistinct privilege from dba_tab_privs;

查询数据库的表空间

sql>selecttablespace_name from dba_tablespaces;

在建立用户时,oracle会把用户的信息存放到数据字典中,当给用户授予权限时或是角色时,oracle会将权限和角色的信息存放到数据字典。

如何查询一个角色下有多少权限

a.一个角色包含的系统权限

sql>select *from dba_sys_privs where grantee=‘CONNECT‘;

b.一个角色包含的对象权限

sql>select *from dba_tab_privs where grantee=‘CONNECT‘;

oracle究竟有多少中角色

sql>select *from dba_roles;

如何查看某个用户,具有什么样的角色?

sql>select *from dba_role_privs where grantee=‘SCOTT‘;

dba_user可以显示所有数据库用户的详细信息

数据库字典视图dba_sys_privs可以显示用户所具有的系统权限;

数据库字典视图dba_tab_privs可以显示用户所具有的对象权限;

数据库字典视图dba_col_privs可以显示用户具有的列权限

数据库字典视图dba_role_privs可以显示用户所具有的角色

显示当前用户可以访问的所有数据字典视图

Sql>select *from dict where comments like ‘%grant%’;

显示当前数据库的全称

Sql>selct  * from global_name;

管理表空间和数据文件

表空间是数据库的逻辑组成部分。从物理上讲,数据库数据存放在数据文件中;从逻辑上讲,数据库则是存放在表空间中,表空间由一个或多个数据文件组成

Oracle中逻辑结构包括表空间、段、区、块

数据库有表空间构成,而表空间又是由段构成,而段又是由区构成,而区又是由oracle块构成的这样的一种结构,可以提高数据库的效率

表空间用于从逻辑上组织数据库的数据。数据库逻辑上是由一个或多个表空间组成的。通过表空间可以达到如下作用:

(1)  控制数据库占用磁盘空间

(2)  dba可以将不同数据类型部署到不同的位置,这样有利于提高

I/o性能,同时利于备份和恢复等管理操作

建立表空间

建立表空间使用create tablespace命令完成的,需要注意是,一般情况下,建立表空间是特权用户或是dba来执行的,如果其它用户来创建表空间,则用户必须具有createtablespace的系统权限

建立数据表空间

在建立数据库后,为便于管理表,最好建立自己的表空间

Createtablespace data01 datafile ‘d:\test\data01.dbf’ size 20m uniform size 128k

说明:执行完上述命令后,会建立名称为data01的表空间,并为该表空间建立名称为data01.dbf的数据文件,区的大小为128k

使用数据表空间

Createtable mypart(deptno number(4),dname varchar2(14),loc varchar2(13)) tablespacedata01;

改变表空间的状态

当建立表空间时,表空间处于联机的(online)状态,此时该表空间是可以访问的,并且表空间可以读写的,即可以查询该表空间的数据,而且还可以在表空间执行各种语句。但是在进行系统维护或是数据维护时,可能需要改变表空间啊的状态。一般情况下,由特权用户或是dba来操作

1)使表空间脱机

Sql>altertablespace 表空间名 offine;

2)使表空间联机

Sql>altertablespace表空间名online;

3)只读表空间

当建立表空间时,表空间可以读写,如果不希望在该表空间上执行update,delete,insert操作,那么可以将表空间修改为只读

Sql>altertablespace表空间名read only;

Sql>altertablespace 表空间名 read write;

知道表空间名,显示该表空间包括的所有表

Select * fromall_tables where tablespace_name=”表空间名’

知道表名,查看该表属于哪个表空间

Selecttablespace_name,table_name from user_tables where table_name=’emp’;

删除表空间

一般情况下,由特权用户或dba来操作

Sql>droptablespace ‘表空间’ includingcontents and datafiles;

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

扩展表空间

表空间是由数据文件组成的,表空间的大小实际上就是数据文件相加后的小。那么我们可以想象,假定表employee存放到data01表空间上,初始大小时2m,当数据满2m后,如果向employee表插入数据,这样就会显示空间不足的错误

扩展表空间有三种方法:

1)       增加数据文件

Sql>altertablespace sp01 add datafile ‘d:\test\sp01.dbf’ size 20m

2)增加数据文件的大小

Sql>altertablespace 表空间名 ‘d:\test\sp01.dbf’resize 20m

这里需要注意的是数据文件的大小不要超过500m

3)设置文件的自动增长

Sql>altertablespace 表空间名 ‘d:\test\sp01.dbf’autoextend on next 10m maxsize 500m;

移动数据文件

1)确定数据文件所在的表空间

Selecttablespace_name from dba_data_files where file_name=’d:\test\sp01.dbf’;

2)使用表空间脱机

确保数据文件的一致性,将表空间转变为offline的状态

Sql>alter tablsespacesp01 offline;

3)使用命令移动数据文件到指定的目标位置

Sql>host moved:\test\sp01.dbf  c:\test\sp01.dbf;

4)执行alter tablespace命令

物理上移动了数据后,还必须执行altertablespace命令对数据库文件进行逻辑修改

Sql>altertablespace sp01 rename datafile ‘d:\tst\sp01.dbf’ to ‘c:\test\sp01.db’;

5)使表空间联机

在移动了数据文件后,为了使用户可以访问该表空间,必须将其转变为online状态:

Sql>altertablespace data01 online;

显示表空间信息

查询数据字典师傅dba_tablespaces,显示表空间的信息:

Sql>selecttablespace_name from dba_tablespaces;

显示表空间所包含的数据文件

查询数据字典视图dba_data_files,可显示表空间所包含的数据文件,如下

Sql>selectfile_name,bytes from dba_data_files where tablespace_name=’表空间名’;

数据的完整性用于确保数据库遵从一定的商业和逻辑规则。在oracle中,数据完整性可以使用约束、触发器、应用程序(过程、函数)三种方法来实现,在这三种方法中,因为约束易于维护,并且具有最好的性能,所以作为维护数据完整性的首选。

约束

约束用于确保数据库满足特定的商业规则。在oracle中,约束包括:not null(非空)、uniques(唯一,该列值是不能重复,但可以为空),primary key(主键,该列不能重复且不能为空),foreign key(外键) 和check(列必须满足条件)

注意:一张表最多只能有一个主键,但是可以有多个unique约束。

商店表的设计

Sql>create tablegoods(

       goodsId char(8) primary key,

       goodsName varchar2(30),

       unitprice number(10,2)check(unitprice>0),

       category varchar2(8),

       provider varchar2(30));

sql>create tablecustomer(

       customerId char(8) primary key,

       name varchar2(30) not null,

       address varchar2(50),

       email varchar2(50) unique,

       sex char(2) default ‘男’ check(sex in(‘男’,’女’)),

       cartId char(18));

sql>create tablepurchase(

       customerId char(8) referencescustomer(customerId),

       goodsId char(8) referencesgoods(goodsId),

       nums number(10) check (num between 1 and30));

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

维护

Sql>alter talbegoods modify goodsName not null;

Sql>alter tablecustomer add constraint unique(cardId);

Sql>alter tablecustomer add constraint addresscheck check(address in (‘郑州’,’洛阳’));

删除约束

Sql >alter table表名 drop constraint 约束名称

在删除主键约束的时候,可能有错误,这是因为如果在两张表存在主从关系,那么在删除主表的主键约束时,必须带上cascade选项,如:

Sql>alter table 表名 drop primary key cascade;

显示约束信息

1.通过约束信息

通过查询数据字典视图user_constraints,可以显示当前用户所有的约束信息

Selectconstraint_name,constraint_type,status,vaildated from user_constraints wheretable_name=’表名’;

2.显示约束列

通过查询数据字典视图user_cons_columns,可以显示约束所对应的列信息

Sql>selectcolumn_name,position from user_cons_columns where constraint_name=’约束名’;

3.通过pl/sql developer工具

列级定义

列级定义是在定义列的同时定义约束

如在department表定义主键约束

Create tabledepartment(dept_id number(2) constraint pk_department primary key,

Name varchar2(12),

Loc varchar2(12));

表级定义

表级定义是指在定义了所有列后,再定义约束,这里需要注意:not nul约束只能在列级上定义。

Create tableemployee(

Emp_id number(4),

Name varchar2(15),

Dept_id number(2),

Constraintpk_employee primary key (emp_id) references deptment(dept_id));

管理索引

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

单列索引

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

Createindex 索引名 on 表名(列名)

Sql>create indexnameIndex on customer(name);

复合索引

复合索引是基于两列或是多列的索引。在同一张表上可以有多个索引,但是要求列的组合必须不同,比如:

sql>create indexemp_idx1 on emp(ename,job);

sql>create indexemp_idx1 on emp(job,ename);

oracle的扫描是从后往前扫的,应该把能减小查询范围的写在后面这样可以提高效率。

使用索引的原则

  1. 在大表上建索引才有意义
  2. 在where子句或是连接条件上经常引用的列上建立索引
  3. 索引的层次不要超过4层

索引缺点

  1. 建立索引,系统要占用大约为表的1.2倍的硬盘和内存空间来保存索引。
  2. 更新数据的时候,系统必须要有额外的时间来同时对索引进行更新,以维持数据和索引的一致性。

在下列字段建立索引应该是不恰当的:

  1. 很少或从不引用的字段
  2. 逻辑型字段

显示表的所有索引

在同一张表上可以有多个索引,通过查询数据字典视图

Dba_indexs和user_indexs,可以显示索引信息,其中dba_indexs拥有显示数据库所有的索引信息,而user_indexs用于显示当前用户的索引信息:

Sql>selectindex_name,index_type from user_indexs where table_name=’表名’;

显示索引列

通过查询数据字段视图user_ind_columns,可以显示索引对应的列的信息

Sql>selecttable_name,column_name form user_ind_columns where index_name=’IND_ENAME’;

也可以通过pl/sql developer工具

Pl/sql编程

Pl/sql是oracle在标准的sql语言上的扩展。Pl/sql不仅允许嵌入sql语言,还可以定义变量和常量,允许使用条件语句和循环语句,允许使用例外处理各种错误,这样使得它的功能变得更加强大。

注意:

  1. 过程,函数,触发器是pl/sql编写的。
  2. 过程、函数、触发器是存在于oracle中。
  3. Pl/sql是非常强大的数据库过程语言。
  4. 过程,函数可以在java程序中调用。

好处:

  1. 提高应用程序的运行性能
  2. 模块化的设计思想(分页的过程,订单的过程,转账的过程…)
  3. 减少网络传输量
  4. 提高安全性

缺点:移植性不好

编写一个存储过程,该过程可以向某表中添加记录。

创建过程:(replace代表如果存在sp01就替换)

Sql>Createor replace procedure sp01 is

Begin

--执行部分

Insertinto mytest(‘李枭龙’,’12345678’);

End;

如何查看错误信息:

Sql>showerror;

调用存储过程:

  1. exec 过程名(参数值1,参数值2…)
  2. CALL 过程名(参数值1,参数值2…)

 Pl/sql的基本单位块,通过块我们可以编写过程(存储过程)、函数、触发器、包

编写规范:

  1. 1.  注释

单行注释:--

Select * from empwhere empno=7788;--取得员工信息

多行注释

/*…*/来划分

  1. 2.  标识符号的命名规范

1)       定义变量时,建议用v_作为前缀 v_sal

2)       定义常量时,建议用c_作为前缀 c_rate

3)       定义游标时,建议用_cursor作为前缀 emp_cursor

4)       定义例外时,建议用e_作为前缀 e_error

块(block)是pl/sql的基本程序单元,编写pl/sql程序实际上就是编写pl/sql块。

Pl/sql由三个部分构成:定义部分、执行部分、例外处理部分。

Declar

/*定义部分---定义常量、变量、游标、例外、复杂实际类型*/

Begin

/*执行部分—要执行pl/sql语句和sql语句*/

Exception

/*例外处理部分—处理运行的各种错误*/

End;

定义部分是从declare开始的,该部分是可选的

执行部分是从begin开始的,该部分是必须的,

例外处理部分是从exception开始的,该部分是可选的。

 实例一:只包括执行部分的pl/sql块

Setserveroutput on –打开输出选项

Begindbms_output.put_line(‘hello’);

End;

相关说明:

dbms_output是oracle所提供的包(类似java开发包),该包包含一些过程,put_line就是dbms_output包的一个过程。

实例二-包含定义部分和执行部分的pl/sql块

Declare

     v_ename varchar2(5);--定义字符串变量

     v_sal number(7,2);

begin

selectename,sal into v_ename,v_sal from emp where empno=&no;

dbms_output.put_line(‘雇员名:’||v_ename||’ 工资:’||v_sal);

end;

/

相关说明:

&表示要接受从控制台输入的变量

into表示把查出的ename赋值给v_ename;

||字符串连接符

实例3-包含定义部分、执行部分、和例外部分处理部分

Declare

     v_ename varchar2(5);--定义字符串变量

begin

selectename into v_ename from emp where empno=&no;

dbms_output.put_line(‘雇员名:’||v_ename);

--异常处理

exception

whenno_data_found then

dbms_output.put_line(‘小盆友,你的编号输入有误!’);

end;

/

相关说明:oracle事先预定义了一些例外,no_data_found就是找不到数据的例外。

过程

过程用于执行特定的操作。当建立过程时,即可以指定输入参数(in),也可以指定输出参数(out)。通过在过程中使用输入参数,可以将数据传递到执行部分;通过使用输出参数,可以将执行部分的数据传递到应用环境。在sqlplus中可以使用create procedure命令来建立过程。

实例一:编写一个过程,可以输入雇员名,新工资可修改雇员的工资

createprocedure sp02(spName varchar2,newSal number) is

begin

--执行部分,根据用户名去修改工资

updateemp set sal=newSal where ename=spName;

end;

实例二:如何在java程序中调用一个存储过程

创建CallableStatement

CallableStatementcs=ct.prepareCall(“{call sp02(?,?)}”);

给问号赋值

cs.setString(1,”SMITH”);//第一个参数

cs.setInt(2,9830);//第二个参数

执行

cs.execute();

函数

函数用于返回特定的数据,当建立函数时,在函数头部必须包含return字句,而在函数体内必须包含return语句返回的数据。我们可以使用create function来建立函数,如下:

--输入雇员姓名,返回该雇员的年薪

createfunction sp01(spName varchar2)

returnnumber is yearSal number(7,2);

begin

--执行部分

selectsal*12+nvl(comm,0)*12 into yearSal from emp where ename=spName;

returnyearSal;

end;

函数调用

sql>var incomenumber

sql>callsp01(‘SCOTT’) into:income;

sql>print income

同样我们可以在java程序中调用该函数

selectsp01(‘SCOTT’) from dual;

可以通过cs.getInt(1)得到返回结果

包用于在逻辑上组合过程和函数,它由包规范和包体两部分组成。

  1. 我们可以使用createpackage命令来创建包:

实例:

create package sp01is

procedureupdate_sal(name varchar2,newsal number);

functionannual_income(name varchar2) return number;

end;

包的规范只包含了过程和函数的说明,但是没有过程和函数的实现代码。包体用于实现包规范中的过程和函数

  1. 建立包体可以使用createpackage body命令

CREATE OR REPLACE

PACKAGE BODYSP_PACKAGE AS

  procedure update_sal(name varchar2,newsalnumber) AS

  BEGIN

    /* TODO 需要实施 */

    update scott.emp set sal= newsal whereename=name;

  END update_sal;

  function annual_income(name varchar2)returnnumber AS

/* 声明变量 */

 annual_salary NUMBER;

  BEGIN

    /* TODO 需要实施 */

   select sal*12+nvl(comm,0)into annual_salaryfrom scott.emp where ename=name;

    return annual_salary;

  END annual_income;

END SP_PACKAGE;

如何调用包的过程或是函数

当调用包的过程或是函数时,在过程和函数前需要带有包名,如果需要访问其它方案的包,还需要在包名前加方案吗。如:

sql>callsp_package.update_sal(‘SCOTT’,1500);

特别说明:

包是Pl/sql中非常重要的部分,我们在使用过程分页时,将再次体验它的威力

触发器

触发器是指隐含的执行的存储过程。当定义触发器时,必须指定触发的事件和触发的操作,常用的触发事件包括insert,update,delete语句,而触发器操作实际就是一个pl/sql块。可以使用create trigger来建立触发器。

pl/sql程序中的变量和常量

  1. 标量类型(scalar

在编写pl/sql块时,如果要使用变量,需在定义部分定义变量来存储最简单的变量。

pl/sql中定义变量和常量的语法如下:

identifier[constant] datatype [not null] [:=| default expr]

identifier:名称、datatype:数据类型、not null:指定变量值不能为null

:=给变量或是常量指定初始值

default 用于指定初始值

expr:指定初始值的pl/sql表达式,可以使文本值、其他变量、函数等

标量定义的案例

①  定义一个边长字符串

v_enamevarchar2(10);

②  定义一个小数范围-9999.99~9999.99

v_salnumber(6,2);

③  定义一个小数并给一个初始值为5.4 :=是pl/sql的赋值号

v_sal2number(6,2):=5.4

④  定义一个日期类型的数据

v_hiredatedate;

⑤  定义一个布尔变量,不能为空,初始值为false

v_validboolean not null default false;

定义好变量后,就可以使用这些变量:

下面以输入员工号、显示雇员姓名、工资、个人所得税(税率为0.03)为例。

set serveroutputon;

declare

c_tax_ratenumber(3,2):=0.03;

--用户名

v_ename scott.emp.ename%type;

v_sal scott.emp.sal%type;

v_tax_salNUMBER(7,2);

BEGIN

--执行

SELECT ename,salINTO v_ename,v_sal FROM scott.emp where empno=&no;

--计算所得税

v_tax_sal:=v_sal*c_tax_rate;

--输出

dbms_output.put_line(‘姓名是:‘|| v_ename || ‘工资:‘ || v_sal || ‘交税:‘ || v_tax_sal);

end;

/

标量(scalar)使用%type属性定义变量,这样它会按照数据库例来确定你定义的变量的类型和长度。使用:

标识符名 表名.列名%type;

  1. 2.  复合类型(composite

用于存放多个值的变量。主要包括这几种:

pl/sql记录:类似于结构体,需要注意的是,当引用pl/sql记录成员时,必须要加记录变量作为前缀(记录变量.记录成员)如下:

declare

--定义一个pl/sql记录类型emp_record_type类型包含三个数据

typeemp_record_type is record(

namescott.emp.ename%type,

salaryscott.emp.sal%type,

titlescott.emp.job%type);

--定义一个变量sp_record是emp_record_type

sp_recordemp_record_type;

begin

selectename,sal,job into sp_record from scott.emp where empno=7788;

dbms_output.put_line(‘员工名:’ || sp_record.name);

end;

pl/sql表:相当于数组,但是需要注意的是高级语言中数组的小标不能为负数,pl/sql是可以为负数的,并且表元素的下标没有限制。如:

declare

--定义一个pl/sql表类型sp_table_type,该列类型用来存放--scott.emp.ename%type,index by binary_integer表示下标--是整数

typesp_table_type is table of scott.emp.ename%type

indexby binary_integer;

--定义了一个sp_table变量,这个变量类型是sp_table_type

sp_tablesp_table_type;

begin

selectename into sp_table(0) form scott.emp where empno=7788;

dbms_output.put_line(‘员工名:’||sp_table(0));

end;

说明:

sp_table_type是pl/sql表类型

scott.emp.ename%type指定了表的元素的类型和长度

sp_table为pl/sql表变量

sp_table(0)则表示下标为0的元素

嵌套表(nested table)

varray

  1. 3.  参照类型(reference

参照变量是指用于存放数值指针的变量。通过使用参照变量,可以使得程序共享相同对象,从而降低占用的空间。在编写pl/sql程序时,可以使用游标变量(ref cursor)和对象类型变量(ref obj_type)两种参照变量类型

游标变量(refcursor):使用游标时,当定义游标时不需要指定相应的select语句,但是当使用游标时(open时)需要指定select语句,这样一个游标就与一个select语句结合了。

①     使用pl/sql编写一个块,可以输入部门号,并显示该部门所有员工姓名和其他工资

declare

--定义游标类型

type sp_emp_cursoris REF CURSOR;

--定义一个游标变量

test_cursorsp_emp_cursor;

--定义变量

v_enamescott.emp.ename% TYPE;

v_salscott.emp.sal% TYPE;

BEGIN

--执行

--把test_cursor和一个select 结合游标指向select语句集

open test_cursorfor select ename,sal FROM scott.emp where deptno=&no;

--循环取出

loop

 fetch test_cursor INTO v_ename,v_sal;

--判断工资高低,决定是否更新可以用if语句

 --判断是否test_cursor为空

exitwhen test_cursor%notfound;

dbms_output.put_line(‘名字:‘||v_ename||‘工资:‘||v_sal);

end loop;

end;

②在①基础上,如果某个员工的工资低于2000元,就给该雇员工资增加10%

--如果某个员工的工资低于2000元,就给该雇员工资增加10%

create or REPLACEprocedure sp03(spName varchar2) is

--定义

v_salscott.emp.sal% TYPE;

begin

--执行

SELECT sal intov_sal from scott.emp where ename=spName;

--判断

if v_sal<2000then

UPDATE scott.empset sal=sal*1.1 where ename=spName;

end if;

end;

可以输入一个员工名,如果该雇员的补助不是0就在原理的基础上增加100;如果补助为0就把补助设为200;

--如果某个员工的工资低于2000元,就给该雇员工资增加10%

create or REPLACEprocedure sp03(spName varchar2) is

--定义

v_comm scott.emp.comm%TYPE;

begin

--执行

SELECT comm into v_commfrom scott.emp where ename=spName;

--判断

if v_sal<>0then

UPDATE scott.empset comm=comm+100 where ename=spName;

else

update scott.empset comm=comm+200 where ename=spName;

end if;

end;

可以输入一个雇员编号,如果该雇员的职位是PRESIDENT就给他的工资增加1000,如果该雇员的职位是MANAGER就给他的工资增加500,其他职位的雇员工资增加200.

createor REPLACE procedure sp01(spNo number) is

v_jobemp.job% TYPE;

begin

selectjob into v_job from scott.emp where empno=spNo;

ifv_job=‘PRESIDENT‘ THEN

updateemp set sal=sal+1000 where empno=spNo;

elseif v_job=‘MANAGER‘ THEN

updateemp set sal=sal+500 where empno=spNo;

else

updateemp set sal=sal+200 where empno=spNo;

endif;

endif;

end;

循环语句-loop

它是pl/sql中最简单的循环语句,这种循环语句以loop开头,以end loop结尾,这种循环至少会被执行一次。

案例:编写一个过程,可以输入用户名,并循环添加10个用户到users表中,用户编号从1开始增加。

createor REPLACE procedure sp05(spName VARCHAR2) is

--定义部分

v_numNUMBER :=1;

begin

loop

insertinto users values(v_num,spName);

--判断是否要退出循环

exitWHEN v_num=10;

--自增

v_num:=v_num+1;

endloop;

end;

循环语句-while循环:

至少执行循环体一次,而对于while循环来说,只有条件为true时,才会执行循环体语句。

添加10条记录

createor REPLACE procedure sp05(spName VARCHAR2) is

--定义部分

v_numNUMBER :=1;

begin

whilev_num<20 loop

insertinto users values(v_num,spName);

--自增

v_num:=v_num+1;

endloop;

end;

循环语句-for循环

基本for循环的基本结构如下

begin

     for i in reverse 1..10 loop

     insert into users values(i,’李枭龙’);

     end loop;

end;

顺序控制语句-goto,null

①     goto语句

goto语句用于跳转到特定标号去执行语句。注意由于使用goto语句会增加程序的复杂性,并使得应用程序可以读性变差,所以在做一般应用开发时,不建议使用goto语句。

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

declare

iint :=1;

begin

     loop

     dbms_output.put_line(‘输出i=’||i);

ifi=10 then

     goto end_loop;

endif;

i:=i+1;

endloop;

<<end_loop>>

dbms_outout.put_line(‘循环结束’);

end;

顺序控制语句-null

②null语句不会执行任何操作,并且会直接将控制传递到下一条语句。使用null语句的主要好处是可以提高pl/sql的可读性。

declare

v_salscott.emp.sal%type;

v_enamescott.emp.ename%type;

begin

selectename,sal into v_ename,v_sal from scott.emp where empno=&no;

ifv_sal<3000 then

updatescott.emp set comm=sal*0.1 where ename=v_ename;

else

null;

endif;

end;

 

4.lob(large object)

分页

无返回值的存储过程

 编写一个过程,可以向book表添加书,通过java程序调用

--in代表这是一个输入参数,默认为in

--out表示一个输出参数

createor REPLACE PROCEDURE sp06(

spBookIdin number,spbookName in VARCHAR2,sppublishHouse in VARCHAR2) is

begin

insertinto book values(spBookId,spbookName,sppublishHouse);

end;

--在java中调用

//1.加载驱动

class.forName(“oracle.jdbc.driver.OracleDriver”);

Connectionct=DriverManager.getConnection(“jdbc:oracle:thin:@127.0.0.1:1521:ORCL”,”scott”,”li1127593600”);

//2.创建callableStatement

CallableStatementcs=ct.prepareCall(“{call sp06(?,?,?)}”);

//给?赋值

cs.setInt(1,10);

cs.setString(2,”笑傲江湖”);

cs.setString(2,”人民出版社”);

//执行

cs.execute();

有返回值的存储过程(非列表)

案例:编写一个过程,可以输入雇员的编号,返回该雇员的姓名、工资、和岗位。--有输入和输出的存储过程

--有输入和输出的存储过程

createor REPLACE procedure sp07(

spnoin number,spName out VARCHAR2,spSal out number,spJob out VARCHAR2) is

begin

selectename,sal,job into spName,spSal,spJob from scott.emp where empno=spno;

end;

java程序:

package me.lxl.study;import java.sql.CallableStatement;import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;public class TestOracle {     public static void main(String [] args){         CallableStatement cs=null;         Connection ct=null;         try {              Class.forName("oracle.jdbc.driver.OracleDriver");         ct=DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:ORCL","lxl","li1127593600");              cs=ct.prepareCall("{call sp07(?,?,?,?)}");              cs.setInt(1, 7788);              cs.registerOutParameter(2, oracle.jdbc.OracleTypes.VARCHAR);              cs.registerOutParameter(3, oracle.jdbc.OracleTypes.DOUBLE);              cs.registerOutParameter(4, oracle.jdbc.OracleTypes.VARCHAR);              //执行              cs.execute();              //取出返回值,要注意?顺序              String name=cs.getString(2);              String job=cs.getString(4);              System.out.println("7788的名字:"+name+"工作:"+job);         } catch (Exception e) {              // TODO: handle exception              e.printStackTrace();         }finally{         //关闭各个打开的资源。。              try {                   cs.close();                   ct.close();              } catch (SQLException e) {                   // TODO Auto-generated catch block                   e.printStackTrace();              }         }     }}

 

有返回值的存储过程(列表[结果集]

案例:编写一个过程,输入部门号,返回该部门所有雇员信息。分析如下:由于oracle存储过程没有返回值,它的返回值都是通过out参数来替代的,列表同样也不列外,但由于是集合,所以不能用一般的参数,必须用package了。所有要分两部分:

①  建一个包。如下:

create or replacepackage testpackage as type test_cursor is ref cursor;

end testpackage;

②  创建一个过程

create or REPLACEPROCEDURE sp08(

spNo in NUMBER,p_cursorout testpackage.test_cursor)is

BEGIN

open p_cursor forselect * from scott.emp where deptno=spNo;

end;

③  java程序代码

CallableStatementcs=ct.prepareCall(“{call sp08(?,?)}”);

cs.setInt(1,10);

cs.registerOutParameter(2,oracle.jdbc.OracleTypes.CURSOR);

cs.execute;

//得到结果集

ResultSetrs=(ResultSet)cs.getObject(2);

while(rs.next()){

System.out.println(rs.getInt(1)+”“+rs.getString(2));

编写分页过程

要求可以输入表名,每页显示记录数,当前页。返回总记录数、总页数、和返回的结果集。

在分页的时候,可以把下面的sql语句当作模板使用

select* from (select t1.*,rownum rn from (select * from scott.emp)t1 whererownum<=10)where rn>=6;

分页过程:

--开始编写分页的过程

create orREPLACE PROCEDURE fenye

(tableName inVARCHAR2,

--一页显示记录数

pagesize innumber,

pageNow innumber,

--总记录数

myrows outnumber,

--总页数

mypagecount outNUMBER,

--返回的记录集

p_cursor out testpackage.test_cursor

) is

--定义部分

v_sqlVARCHAR2(1000);

v_beginNUMBER:=(pageNow-1)* pagesize+1;

v_endNUMBER:=pageNow* pagesize;

begin

v_sql:=‘ select* from (select t1.*,rownum rn from (select * from ‘|| tablename ||‘ order bysal) t1 where rownum<=‘|| v_end ||‘)where rn>=‘|| v_begin;

--把游标和sql关联

open p_cursorfor v_sql;

--计算myrows和mypagecount

--组织一个sql

v_sql:=‘selectcount(*) from ‘|| tablename;

--执行sql,并把返回的值,赋给myrows

EXECUTEimmediate v_sql into myrows;

if mod(myrows,pagesize)=0 then

mypagecount:= myrows/pagesize;

else

mypagecount:=myrows/ pagesize+1;

end if;

--关闭游标

CLOSE p_cursor;

end;

java调用过程代码:

package me.lxl.study; import java.sql.CallableStatement;import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.SQLException; public class FenYe {      public static void main(String[] args) {         // TODO Auto-generated method stub         CallableStatement cs=null;         Connection ct=null;         ResultSet rs=null;         try {              Class.forName("oracle.jdbc.driver.OracleDriver");         ct=DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:ORCL","lxl","li1127593600");              cs=ct.prepareCall("{call fenye(?,?,?,?,?,?)}");              //给?赋值              cs.setString(1, "scott.emp");              cs.setInt(2, 5);              cs.setInt(3, 1);              //注册总记录数              cs.registerOutParameter(4, oracle.jdbc.OracleTypes.INTEGER);              //注册总页数              cs.registerOutParameter(5, oracle.jdbc.OracleTypes.INTEGER);              //注册返回的结果集              cs.registerOutParameter(6, oracle.jdbc.OracleTypes.CURSOR);              //执行              cs.execute();              //取出总结录数,注意:getInt(4)中4是由该参数的位置决定的              int rowNum=cs.getInt(4);              int pageCount=cs.getInt(5);              rs=(ResultSet)cs.getObject(6);              //显示一下              System.out.println("rowNum="+rowNum);              System.out.println("pageCount="+pageCount);              while(rs.next()){                   //集合里的getInt(4)是取的第四列                   System.out.println("编号:"+rs.getInt(4)+"名字:"+rs.getString(2)+"薪水:"+rs.getFloat(6));                                }         } catch (Exception e) {                      e.printStackTrace();         }finally{         //关闭各个打开的资源。。              try {                   rs.close();                   cs.close();                   ct.close();              } catch (SQLException e) {                   // TODO Auto-generated catch block                   e.printStackTrace();              }                      }     } } 

 

pl/sql-例外处理

例外的分类

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

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

 

 

 

 

 

 

 

zeri_divide当执行2/0语句时,则会触发该例外

 

 

 

非预定义例外用于处理预定义例外不能处理的例外

自定义例外用于处理与oracle错误无关的其他情况

createor replace procedure test(spNo number)

is

--定义一个例外

myexexception;

begin

updatescott.emp set sal=sal+1000 where empno=spNo;

--sql%notfound这是表示没有update

--raisemyex;触发myex

ifsql%notfound then

raisemyex

endif;

exception

whenmyex then

dbms_output.put_line(‘没有更新任何用户’);

end;

视图

视图是一个虚拟表,其内容由查询定义。同真实的表一样,视图包含一系列带有名称的列和行数据。但是,视图并不在数据库中以存储的数值集形式存在。行和列数据来自由定义视图的查询所引用的表,并且在引用视图时动态生成

创建视图

sql>createview 视图名 as select 语句 [with read only]

创建或修改视图

sql>createor replace view 视图名 as select语句[with read only]

删除视图

sql>dropview 视图名

 

 

 

 

 

oracle笔记