Oracle 笔记
来源:互联网 发布:uc浏览有网络却打不开 编辑:程序博客网 时间:2024/06/02 20:16
第1页
1. Oracle 的使用
1.1. SQLPLUS 的命令
初始化表的位置:
setNLS_LANG=american_america.us7ascii (设置编码才可以使用下面脚本)
cd$ORACLE_HOME/rdbms cd demo summit2.sql
*********************************
我们目前使用的是oralce 9i 9201 版本
select * fromv$version;
恢复练习表命令:
sqlplus **/** @summit2.sql //shell要在这个文件的位置。
登陆 oracle的命令:
sqlplus 用户名/密码
show user 显示当前登陆的身份.
set pause on
set pause off 分页显示.
oracle 中默认日期和字符是左对齐,数字是右对齐
table or viewdoes not exist ; 表或示图不存在
edit 命令用于自动打开vi 修改刚修执行过的 sql 的命令。
修改方法二:
l 3 先定位到行 c /旧串/新串
执行出错时,利用错误号来查错误:
!oerr ora942 (装完系统后会装一个 oerr 工具,用于通过错误号来查看错误的具
体信息)
想在 sql 中执行unix 命令时,把所有的命令前加一个!就可以, 或者host( 用于
从 sql 从切换至unix环境中去)
/*** 初次使用时注意 ****
运行角本时的命令:
先切换到 unix环境下,cd$oracle_home cd sqlplus cd demo 下面有两个角本
建表语句。 第2页
@demobld.sql
sqlplusnanjing/nanjing @demobid.sql 直接运行角本,后面跟当前目录或者是绝对
路径
保存刚才的 sql 语句: save 命令 第二次保存时要替换之前的角本 save
文件名 replace
把刚才保的 sql 重新放入 buffer 中
spool on 开启记录
spool off 关闭记录
spool 文件名 此命令会把所有的操作存在某个文件中去
常见缩写:
nls nationallanguage support 国家语言支持
1.2. SQL 的结构
|DDL 数据库定义
|DML 数据库管理
SQL――Commitrollback
|DCL 数据库控制
|grant+revoke 权限管理
表分为:系统表(数据字典),用户表
注:知道数据字典可以更便于使用数据库。
1.3. SQL 语句
1.3.1. 纵向投影操作select
select * fromstudent;
selectname||’(‘||id||’)’ EMPLOYEE from employee;
selectname,salary*13 from employee;
NVL function
如果原来的数值是null的话,由指定数值替代。
selectlast_name,title,salary*NVL(commission_pct,0)/100 COMM from s_emp; 第3页
1.3.2. column 使用
column(col) columnName clear/format/heading/justifyformat
column salaryformat $9999999.00 设置数字显示形式
column namefromat a15; 设置字符串显示 15 个字符
column salaryjustify left/right/center 输出格式
column salaryheading text 设置显示的字段名
column clear 清除格式
columnlast_name;显示该字段名所用的格式
column salaryjustify left format $99,999.00 ( 定义工资的显示形式 )
1.3.3. order by
ORDER BY 排序 升序和降序 ASC 升序(默认) DESC 降序
select * froms_emp order by dept_id , salarydesc
部门号升序,工资降序
关键字 distinct 也会触发排序操作。
select * fromemployee order by 1; //按第一字段排序
NULL被认为无穷大。order by 可以跟别名。
1.3.4. where 选择操作(横向投影)
where 条件一定是根据某个字段来进行过滤操作.
select * froms_emp where dept_id=42; 查看部门号为42的所有员工
select * froms_emp where salary>1000 查看工资高于1000 的所有员工
select salaryfrom s_emp wherefirst_name='Geroge' 找出名字为 Geroge 的员
工的工资数
select table_name from user_tables where table_name='S_EMP'; 查某个具
体表名时,表名的字符串必须要为大写
或者采用 upper(table_name)
select * fromuser_talbes where table_name like ‘s/_%’ escape ‘/’;
使用转义字符对关键字进行转义。
逻辑运算:
BETWEEN AND 在什么之间 第4页
NOT BETWEEN AND 注意区间:[ ]是一个闭区间
IN( LIST) 在某个集合中
NOT IN (list) 空值会有影响 (等于 list 其中任何一个就行,
为提高效率常把比例高的放在前面)
LIKE 模糊配置
NOT LIKE 通配比较
IS NULL 是空
AND
OR
NOT
练习 3:(查出 s_emp表中所有员工的一年的总收入)
selectfirst_name , salary*12*( 1+nvl(commission_pct/100 , 0 ) ) " year salary"
from s_emp;
nvl 函数 专用于处理空值的影响.
练习 4:(找出表名以S_开头的所有表)对于一些特殊字符,要用到 escape 转义,并
不是一定要用/,escape后面定义是什么字符为转义字符,那就用哪个字符
select table_name from user_tables where table_name like 'S/_%' escape '/';
1.3.5. 单行函数
单行函数: (dual 哑表 )
字符函数:
lower 转小写 select lower('SQLPLUS') from dual;-->对纯字
符串处理的时候
upper 转大写 select upper('sqlplus') from dual;
initcap 首字符大写 select initcap('tarena') from dual;
concat 连接字符串 select concat(first_name , last_name) from
s_emp;等效于||
substr 求子串 select substr('tarenasd0603' ,1,6) from dual; (取前
六个字符) select substr('tarenasd0603',-2) from dual; (取后两个字符)
length 求字符长度
select length('tarena') from dual;
nvl 空值函数 两个参数的类型要匹配,统一的,表示:如果有,则
返回前面的参数,如果没有就返回后面的参数
eg:selectfirst_name,salary from s_emp where lower(first_name)='george';
select first_name , substr(first_name , -2 )from s_emp; (查出s_emp表中所有
用户名字的最后两个字符)
默认的是从左向右,如果是-2 则表示从右向左数
练习 5 : select first_name , salary from s_emp where 第5页
lower(first_name)='george';
数值函数:
round 函数(四舍五入) select round(45.935, 2) from dual; 不带参数时默认
为 0 位小数
trunc 函数(截取,不管后面的数字) select trunc(45.995, 1) from dual;
日期函数:
oracle 数据库中存放时间格式的数据,是以oracle 特定的格式存贮的,占7 个字
节,与查询时显示的时间格式无关,具体哪个字节表示什么,我不太清楚,请高
手补充。存贮的时间包括年月日时分秒,最小精度为秒,不存贮秒以下的时间单
位。因此在一些前台支持毫秒级的程序(如 PB客户端程序)连接到oracle 数据库
时应注意这点。查询时显示的时间格式,由会话环境决定,或者由用户定义,与
数据库无关。
select sysdatefrom dual; 从伪表查系统时间,以默认格式输出。
sysdate+(5/24/60/60)在系统时间基础上延迟 5 秒
sysdate+5/24/60 在系统时间基础上延迟5 分钟
sysdate+5/24 在系统时间基础上延迟 5 小时
sysdate+5 在系统时间基础上延迟5 天
所以日期计算默认单位是天
内置函数:
months_between(sysdate,addmonth(sysdate,5)) //两个月有多少天。
add_months(sysdate,-5)在系统时间基础上延迟 5 月
add_months(sysdate,-5*12)在系统时间基础上延迟 5 年
last_day(sysdate)一个月最后一天
next_day(sysdate,’Friday’) 下个星期星期几。
round (sysdate,’day’) 不是四除五入了,是过了中午留下,不过的略掉
trunc(sysdate,’month’) 不到一月都省略
例子:
上月末的日期:select last_day(add_months(sysdate, -1))from dual;
本月的最后一秒: selecttrunc(add_months(sysdate,1),'month') - 1/24/60/60from dual
本周星期一的日期:select trunc(sysdate,'day')+1 from dual
年初至今的天数:select ceil(sysdate - trunc(sysdate,'year')) from dual;
格式转换函数:
to_char 显示日期:
从数字转化为 char to_char(date,'格式')
从日期转化为 char to_char(date, 'fmt' )
第6页
yyyy 2007 年份
year two thousand seven 年份
mm 03 (格式缩写显示也缩写)
month march 月份
dy fri 星期几缩写
day Friday 星期几
dd 16 一个月第几天
mi 30 分钟
ss 35 秒钟
hh 18 小时
rr 07 年 最近时间
yy 07 年 当前世纪年份
selectto_char(sysdate, 'yyyy mm dd hh24:mi:ss') from dual;
selectto_char(sysdate, 'fmyyyy mm dd hh24:mi:ss') from dual;
查出三月分入职的员工:
selectfirst_name,start_date from s_emp where to_char(start_date,'mm')='03';
to_date表达日期:
字符转日期
select to_date('2000 11 20', 'yyyy mm dd ') from dual;
select round(to_date('10-OCT-06' ,'dd-mon-RR') )from dual;
to_number
字符转数字
selectto_number('10') from dual ;
函数、表达式、隐式数据类型转换会导致索引用不上,where 条件后面只能放单
行函数,它起了一个过滤的的作用。
1.3.6. 组函数
group by 分组子句 对分组后的子句进行过滤还可以用 having 条件
对分组后的条件进行过滤 where 是对记录进行过滤
avg(distinct |all )求平均值
count(distinct| all )统计 第7页
max(distinct |all ) 求最大值
min(distinct |all )求最小值
sum(distinct |all ) 求和
(所有组函数会忽略空值 , avg sum 只能作用于数字类型)
求有提成员工的提成的平均值;
select avg(nvl(commission_pct ,0 ) ) from s_emp;
有多少人有提成:
select count( commission_pct ) from s_emp ;
count(*) 用于统计记录数:
select sum(commission_pct)/ count(*) from s_emp;
员工分部在多少个不同的部门:count 默认为作 all 的动作
select count(dept_id) from s_emp;
select count(distinct dept_id) from s_emp;
求各个部门的平均工资:group by 子句也会触发排序
select dept_id , avg(salary) aa from s_emp group by dept_id
order by aa ; //对平均工资排序
select dept_id , avg(salary) aa from s_emp group by dept_id;
注意:groupby 子句后面跟有条件只能是组函数查询的结果中的字段,所以我
们会人为在结果要加入一些 group by 要用的字段,如:dept_id 可能不想要。
select region_id , count(*) from s_dept 此句会有错,count(*)是单组分组函
数,如果加上 group by region_id 就是找出同地区的部门数量。
select max(region_id) , count(*) from s_dept; (强制语法上可以正确,但是
不能保证结果也会正确)
求各个部门不同工种的平均工资:
select dept_id , title, avg(salary) from s_emp group by dept_id ,
title ;
哪些部门的平均工资比 2000 高:
select dept_id, avg(salary) aa from s_emp group by (dept_id) having
avg(salary)>2000;
除了 42 部门以外的部门的平均工资:
select dept_id , avg(salary) from s_emp group by (dept_id )having
dept_id!=42; 第8页
select dept_id , avg(salary) from s_emp where dept_id!=42
group by(dept_id ) ;(此种sql 效率要高,先过滤)
再计算)
where 单行函数。
having 组函数。
求各个部门的平均工资:
// 这样统计不详细
select max(d.name) , avg (s.salary) from s_emp s, s_dept d where
s.dept_id=d.id group by d.name;
//****这问题很经典,为了过 oracle sql 语法关而写 max(d.name) ***
select max(d.name) , avg(e.salary) ,max(r.name) from s_emp e, s_dept
d ,s_region r where e.dept_id = d.id and d.region_id=r.id
group by d.id ;
1.3.7. 多表连接
多表连接操作:
两表没有任何关联时会产生迪卡尔机:
select first_name , name from s_emp , s_dept;
1) 等值连接:
练习一:查看员工的姓名和员工部门号:(要考虑到表中实际数据中空值的影响)
select first_name , name from s_emp e, s_dept d wheree.dept_id=d.id;
同时起了别名
select first_name , name from s_emp e, s_dept d wheree.dept_id=d.id and
e.first_name='George';
具体到哪个人所在的部门
表的两边有空值的话,不会显示出来。
练习二:每个员工所在的部门和部门所在的地区
select first_name , s_dept.name, s_region.namefrom s_emp, s_dept, s_region
where
s_emp.dept_id=s_dept.id
and 第9页
s_dept.region_id=s_region.id;
等价于
selectfirst_name,d.name,r.name
from s_empe,s_dept d,s_region r
wheree.dept_id=d.id and d.region_id=r.id;
等值连接:
练习三:找出每个员工和每个员工的工资级别
select a.ename , a.sal, b.grade from emp a ,salgrade b where a.sal between
b.losal andb.hisal;
select a.ename , a.sal, b.grade from emp a , salgrade b where a.sal>=b.losal
and a.sal<=b.hisal;
2) 自连接:
(又名:内连接) 当一个表的插入行之间有了关系时就发生了
select first_name , manager_id from s_emp;
l 查出所有员工的部门领导的名称:( 这种sq 会少一条记录,总经理没有被配置
上)
select e.first_name , m.first_name from s_emp e , s_emp m where
e.manager_id=m.id; //关键是同一张表用不同的别名
3) 外连接:
+)的一方会模拟一条记录配置另一方)这就称为外连接,不 (防止空值忽略,用(
加(+)一个记录都不能少;
select e.first_name , m.first_name from s_emp e , s_emp m where
e.manager_id=m.id(+);
+号放在哪边就表示在哪边补空,来跟对方来匹配,使得数据一个都不会漏掉,
这个例子中的领导有可能会没有(最高领导就再没有领导了,所以就
+号放在可能出现空值的一边)
标准写法:
显示没有员工的部门
select distinct d.name
from
s_emp e,s_deptd 第10页
where
e.dept_id(+)=d.id
and
e.dept_id isnull
显示有员工的部门:
select distinctd.name
from
s_emp e,s_deptd
where
e.dept_id=d.id
1.3.8. 子查询
: Subqueries
,工资最低的那个员工:( 利用子查询 )
关于子查询
找出所有员工中
select first_name, salary from s_emp where salary = ( select
min(salary) from s_emp) ;
selectmax(first_name), min(salary) from s_emp;
//这样写会出错姓名和工资不一致
先运行子查询再运行主查询,子查询一般出现在运算符的 子查询运行的顺序:
值运算符:运算后面只能跟一个值
Smith 干一样的活:
右边。
单
多值运算符:可以对两个以上的值进行操作
查询谁跟
1.先找出 Smith干什么工作
select title from s_emp where last_name='Smith';
2.再在所有数据中找和 Smith工作匹配的人
// ,有潜在性问题 下种写法可能还存在bug,没有考虑到数据的全面性
selec romt last_name , title f s_emp where title =( select title from
s e='Sm_emp where last_nam ith' ) and last_name <> 'Smith' ;
//这种写法才考虑的比较全面 第11页
select last_name , title from s_emp where title in ( select title
from s_emp where last_name='Smith' ) and last_name <> 'Smith' ;
使用子查询时应注意: 单行子查询返回多个结果时会有错误 single-row
subqueryreturns more than one value
查出哪些员工的工资比平均工资低:
selecte.first_name , e.salary
from s_emp e
where
e.salary<
(select avg(nvl( salary,0 ) )
from s_emp)
哪些部门的平均工资比所有部门的平均工资要低:
第一步先查出各个部门的平均工资:
select min(avg(salary)) from s_emp group by dept_id;
第二步再查出哪个部门的工资是最低的:
select dept_id, avg(salary) from s_emp group by dept_id having
avg(salary)= (select min(avg(salary) ) from s_emp group by dept_id ) ;
哪个部门里没有员工:
select deptno from dept where deptno not in ( select
deptno from emp );
哪些人是普通员工:(用子查询形式来做)
selectfirst_name,last_name from s_emp
where id not in
(selectdistinct(manager_id) from s_emp where manager_id is not null);
1.3.9. 语言环境的设置
$ echo $LANG
simplifiedchinese_china.zhs16cgbk
zh_CN.hp15CN
$ echo$NLS_LANG
第12页
1.3.10. E--R 图 实体关系图entity relation
开发编码,测试最终产
品上线试运行。
二范式:表的自连接存在原因,一张表,学生表中也有班级的信息。
它一张表。
了保证数据的一致性,
主键约束 不允许有重复和空值(唯一且非空)
约束 两张表 parent table child table
提高效率而设计的一种与业务无关的
实现,多的一方引用外键
用 FK+UK 实现,
表利用联合主键来实现,
.3.11. DDL 语句:
anguage)数据库定义语句:
table (表)
列号)
reate table [schema].表名 ( 字段名, 字段类型 约束条件);
就是当前用户,严格来访问表名完整的写法是 schema.tablename
定长 不管是否达到最大宽度,都会点最大的宽度。
开发流程先进行需求分析,进行系统设计,建表,再进行
把软件设计模型转化为数据中的表,设计时要考虑性能的设计
第一范式:最简单的一种建方式,一张表只有一个主键。
第
第三范式:表连接存在的原因,两张表,其中一张表引用其
约束:
为
primarykey (pk)
foregin key (fk) 外键
unique key (uk) 唯一可以为空
not null
数据库设计时的注意:
索引: 为了
考虑表点用的物理空间:
考虑表之间的关系:
一对多关系: 利用 FK+PK
一对一关系: 可以利
多对多关系: 通过中间增加一个附加表来实现,附加
联合起来的主键唯一。
1
DDL (DataBaseDefind L
view(示图)
sequence(序
index(索引)
创建表语句:
c
schema 默认
数据类型:
表名的命令规则: 首字母为字母,不得超过 30 个字符
char(size)
varchar2(size) 可变长 按实际的字节占用空间
number 所有的数字类型都称为 number 第13页
number(n, m) n------n 位宽度 m-----小数点后的宽度
number(2,4)小数点后 4 位,有效位 2 位 values(0.0099) 这样可以
存放(在表里只存一个指针)
reate table test(c1 number default 10, c2 number);
.3.12. 表的约束
values(0.01)这样出错
LONG 2GB 大文本一个表最我只允许定义一个 LONG类型(不建议使用)
CLOB 大对象形式
BLOB 存二进制大对象(声音,图像之类)
default 作用演示:
c
1
主键约束的定义:
createtable test(c number primary key ); 列级约束
createtable test(c number , primary key(c) ) ; 表级约束
createtable test( c1 number constraints pkc1 primary key );
此约束有名字: pkc1
createtable test(c number , c2 number , primary key (c ,c1) ) ;
用表级约束可以实现联合主键
再定义子表) 外键约束的定义:(先定义父表,
carete table parent(c1 number primary key );
create table child (c number primary key , c2 number references
parent(c1)); //列约束
create table child( c number primary key , c2 number , foreign key(c2)
references parent(c1)); //表约束
on delete cascade (及联删除,删除父表时子表也跟着删除)
on delete set null (及联删除父表时子表中引用的字段为null)
create tablechild(id number, parent_id number(10) constraint child_fk references
parent(id) ) ondelete cascade
create tablechild(id number, parent_id number(10) constraint child_fk references
parent(id) ) ondelete set null
不给约束起名字时,系统给约束起名时的规律为:数据库用户名_数字(约束名也 第14页
不能重名)
定义一个约束的两种形式:
空约束:
l (利用desc 可能看到)primary key 自动具有非空约束的特点
主键和外键
test(c1 number check(c1>1000));
制表的语法(仅限于Oracle):
列级约束 表级约束
非
not nul
非
check 约束:
create table
此表中要求 c1的值必须要大于1000 才为有效值 .
复
create tablechild1 as select * from child;
利用已知表建一张新表:只会把非空约束带过来,其它约束要自己添加
create table s_emp_42 as select * from s_emp where dept_id
= 42;
只取要表结构,不想要表中数据的建表方式:
createtable s_emp_copy as select * fr m s_emp where 1=2; o
(
看一张表的约束:( 查数据字典示图)
中会查到相应的信息)
这是一个小技巧,利用永不等式提取零条数据,在 JDBC 的学习中会用到where
1=1 的形式,注意体会)
查
desc user_constraints;(这个数据字典
select constraint_name, constraint_type s from user_con traints where
table_name='S_EMP';
k
只定义在示图中(with check option 相当于组示图加了一个约
也是出现在示图中
C来表示
看字段约束的方法:
P pk
R fk
C chec
U UK
V 这种
束)
O
非空约束和CHECK 都是用
查
desc user_cons_columns; 第15页
select column_name, position from user_cons_columns where
constraint_name='S_EMP_ID_PK';
position 的含义:联合主键,约束名一样。
user_constraintsuser_cons_columns 两张表的约束名相等,表名相等,两张表
一关联就可以查出所需的信息。
select constraint_name , r_constraint_name from user_constraints where
constraint_type='R' and table_name='S_EMP' ;
数据库建立时,数据字典就会建好。
user_constraints;自己拥有的
all_constraints; 你自己拥有的加上你可以访问的
dba_constraints 所有的
查看当前数据库数据字典的字典(这个示图很重要)
desc dict;
select table_nameform dict where table_name like '%cons%;
示图:
user_objects; user_tables;
select distinct object_type fromuser_objects;
1.3.13. 介绍事务的概念:
commit 提交,此时说明前面所有语句都成功执行
rollback 回退操作,此时会恢复至上一次提交时的状态。
savepoint 设置保存点
注意 insert into 后面可以跟子查询
insertinto s_emp_42 select * from s_emp where dept_id =42;
UPDATE 修改字段值:
update s_emp set dept_id =10 where id =2 ;
update s_emp set commission_pct =10 ;
没有 where 条件时说明是改表中所有的值.
注意:如有外键引用时常会出现外键引用值没有找到等错误?
delete 删除记录命令语法: 第16页
deletefrom s_emp where dept_id=42;
deleteform s_emp ; 没有where 条件时说明删除表中所有的值
注意:如有外键引用时,删除一张表时常会出现不能删除的情况,
原因一 是因为此时正在有人操作表中记录
原因二 此表有其他的表引用,没能设及联删除:
delete 删除一张大表时空间不释放,非常慢是因为占用大量的系统资源,支持回
退操作,空间还被这张表占用着。
truncate table 表名 (删除表中记录时释放表空间)
DML 语句:
表级共享锁: 对于操作一张表中的不同记录时,互不影响
行级排它锁:对于一行记录,oracle 会只允许只有一个用户对它在同一时间进行
修改操作
wait() 等到行级锁被释放,才进行数据操作
drop 一张表时也会对表加锁,DDL排它锁,所以在删除一张表时如果当前还有用
户操作表时不能删除表
alter table 命令用于修改表的结构(这些命令不会经常用):
增加约束:
altertable 表名 add constraint 约束名 primarykey (字段);
解除约束:(删除约束)
alter table 表名 drop primary key(对于主键约束可以直接用此方法,因为
一张表中只有一个主键约束名, 注意如果主键此时还有其它表引用时删除主键
时会出错)
alter table father drop primary key cascade ; (如果有子表引用主键
时,要用此语法来删除主键,这时子表还存在只是子表中的外键约束被及联删除
了)
altertable 表名 drop constraint 约束名;
(怎样取一个约束名:1、人为的违反约束规定根据错误信息获取!
2、查询示图获取约束名!)
alter table 表名 disable from primary key ; (相当于把一个表的主
键禁用)
alter table 表名 enable primary key ;(enable 时会自动去检查表的记录
是不是符合要求,如果有脏数据时必须要先删除脏数据才可以 enable)
*******************************************************************
第17页
增加字段:
alter table 表名 add(字段字 字段类型)
删除字段:
alter table 表名 drop(字段)
alter tbale 表名 drop column 字段 ; (8i 以后才支持)
给列改名:920 才支持
alter table 表名 rename column 旧字段名 to 新字段名;
修改字段
(此时应注意的问题,更改时要看具体值情况之间的转达换, 改为字符类型时,
必须要为空)
alter table 表名 modify( 字段,类型)
更改表中的字段:
update 表名 set 字段 = 值 where 条件
更改表名
rename 旧表名 to 新表名;
删除表:
trucate table 表名:(表结构还在,数据全部删除,释放表所占的空间,
不支持回退,常用删除大表)
1.3.14. oralce 中产生序列(sequence):
createsequence 序列名;
(不带参数时默认为从 1 开始每次递增 1,oracle中为了提高产生序列的效率一
般一次性产生 20 个序列放入当前会话的序列池中备用以加快效率,序列会出现
不连续的动作回退操作不会影响序列取值)
sequence 的参数:
incrementby n 起始值, start with n 递增量,maxvalue n 最大值,
minvalue n 最小值,cycle| no cycle 轮回, cache n 绶存(第一次取时会一次
取多少个 id存起来)
查看 sequence 示图:
desc user_sequences ;
select sequence_name , cache_size ,last_number from user_sequences
where sequence_name like 's_';
select 序列名.currval from dual 查看当前的序列数
第一次执行这个命令会出错,因为还没有序列号放进序列池中,也就是说
currval 读取的是序列池中的数值。
select 序列名.nextval from dual 查看下一个序列数,它会自动给当前
的序列加1,实际上是给序列池中的数值加一,而序列表中加的是缓存的值。 第18页
清空当前会话的内存:
altersystem flush shared_pool;(执行此命令要有 DBA权限,一般用户执行
出错)
修改序列:(此命令不常用,只需了解就行不必深究)
alter sequence 序列名 修改项;
删除序列 sequence
drop sequence 序列名;
1.3.15. 创建示图
creating views(属于了解知识)
desc user_views;
select text from user_views where view_name='TEST1_V1' ;
示图就相当于一条 select 语句,定义了一个示图就是定义了一个 sql 语句,示图不
占空间,使用view不会提高性能,但是能简单化 sql 语句
(扩展知识: oracle 8i 以后的新示图)MV 物化视图(占存储空间,把select
结果存在一个空间,会提高查询视图,增强实时性,但是存在刷新问题,主要应
用在数据仓库中用要用于聚合表)
使用示图的好处:控制数据访问权限.
如何创建一个示图:
create or replace views test_vi as select * from
test1 where c1=1;
此时往表 test1(base table 基表)中插入数据时:表中没能变化,示图中的
数据发生改变
从示图中插数据时相对应的表会发生改变:
往示图中插数据时,会直接插进基表中,查看示图中的数据时,相当于就是执行
创建时的 select 语句。
简单示图:能进行DML操作。
复杂示图:来源于多张表,不能执行DML操作。
1.3.16. 关于利用rownum 分页显示
rownum 有个特点要么等于 1 要么小于某个值, 不能直接等于某个值, 不能大
于某个值。rownum常用于分页显示。
练习:查询出第 5 条数据和第10 条数据之间:
select first_name , rnum from ( select rownum rnum , first_name
from s_emp where rownum <=10 ) wherernum between 5 and 10; 第19页
分面显示:
SELECT * FROM(SELECT a.*, rownum r FROM S_EMP a ) WHERE r
between 5 AND 10;
练习:哪些员工的工资比本部门的平均工资高?
select first_name , salary , avgsal from s_emp e , ( select
dept_id , avg (salary ) avgsal from s_emp group by dept_id ) a
where e.dept_id =a.dept_id and e.salary >a.avgsal;
在示图上加一个 with check option 就相当于给示图加上了约束
create view test_v as select * from test where c =1 with
check option ;
create viewtest_v as select * from test with read option; 定义在视图上的约束,
只读。
同义词:相当于别名的作用(***只需了解***)系统自建的同义词: user_tables
create synonym asd_s_emp for asd_0607.s_emp ;
目的就是为了给 asd_0607_s_emp 表起另一个代替的名称 asd.s_emp;注意这个同
义词只能自己使用;
create public synonym p_s_emp fro asd_0607.s_emp; 创建公共的同义
词,但是要权限.
删除同义词:
drop synonym 同义词名称
1.3.17. 创建索引
Creating indexes(概念很重要对系统的性能影响非常大)
建索引的目的就是为了加快查询速度,使表中数据在做insert语句时就进行排序。
索引是 DML语句触发的,系统自动运行,也可以强制使用索引。
索引的结构
key | rowid
索引就相于一本的书的目录。索引点系统空间,属于表的附属物。删除一个表时,
相对应的索引也会删除。truncate 表时索引结构在,但是数据不存在。
full table scan 全表扫描
用索引就是为了快速定位数据:(理解时就以字典的目录为例)
查看表的 rowid:
select rowid , first_name from s_emp; 第20页
rowid 定义的信息有: object block table
每条记录都有自己的 rowid ,rowid记录了这条记录在数据库中的位置,可以快速
读取。
索引由谁创建:用户,建索引后会使DML操作效率慢,但是对用户查询会提高效
率,这就是我们建索引的最终目的,
创建一个索引:
create index 索引名 on 表名 ( 字段名);
create insex testindex on test(c1, c2);
哪些字段应该建索引:
经常要用 where 的子句的地方,所以要用索引.用不用索引,关键要看所查询的
数据与所有数据的百分比,表越大,查询的记录越少,索引的效率最高.
替换变量:用&符号来定义替换变量支持交互性提示,对于字符性的数字,一定要
写在单引号之间
set verify on
set verify off;
相当于开关变量,用于控制是否显示新旧的sql 语句
select id ,last_name ,salary from s_emp where title='&job_title';
更改交互的提示信息:
accept p_dname prompt ' 提示信息';
定义变量:
define p_dname='abc';
分页的实现语句:(可以正常运行)
select * from ( select rownum rnum , a.* from (select *
from s_emp)a ) where rnum between 5 and 10;
1.4. SQL 语句使用技巧
1.删除表空间
DROP TABLESPACETableSpaceName [INCLUDING CONTENTS [AND
DATAFILES]]
2.删除用户
drop user XXXXcascade; 第21页
3.删除表的注意事项
在删除一个表中的全部数据时,须使用 TRUNCATE TABLE 表名;因为用 DROP
TABLE,DELETE * FROM 表名时,TABLESPACE表空间该表的占用空间并未
释放,反复几次DROP,DELETE操作后,该TABLESPACE 上百兆的空间就被
耗光了。
4.having 子句的用法
having子句对 group by 子句所确定的行组进行控制, having 子句条件中只允许涉
及常量,聚组函数或group by 子句中的列。
5.外部联接"+"的用法
外部联接"+"按其在"="的左边或右边分左联接和右联接.若不带"+"运算符的表中
的一个行不直接匹配于带"+"预算符的表中的任何行,则前者的行与后者中的一
个空行相匹配并被返回.若二者均不带’+’,则二者中无法匹配的均被返回.利用外
部联接"+",可以替代效率十分低下的 not in 运算,大大提高运行速度.例如,下面
这条命令执行起来很慢
用外联接提高表连接的查询速度
在作表连接(常用于视图)时,常使用以下方法来查询数据:
SELECT PAY_NO,PROJECT_NAME
FROM A
WHERE A.PAY_NONOT IN (SELECT PAY_
NO FROM B WHEREVALUE >=120000);
---- 但是若表 A有10000 条记录,表B有10000 条记录,则要用掉30 分钟才能
查完,主要因为 NOT IN要进 行一条一条的比较,共需要 10000*10000次比较
后,才能得到结果。该用外联接后,可以缩短到 1 分左右的时间:
SELECTPAY_NO,PROJECT_NAME
FROM A,B
WHEREA.PAY_NO=B.PAY_NO(+)
AND B.PAY_NO ISNULL
AND B.VALUE>=12000;
6.set transaction命令的用法
在执行大事务时,有时oracle 会报出如下的错误:
ORA-01555:snapshottoo old (rollback segment too small)
这说明oracle 给此事务随机分配的回滚段太小了,这时可以为它指定一个足 第22页
够大的回滚段,以确保这个事务的成功执行.例如
set transactionuse rollback segment roll_abc;
delete fromtable_name where ...
commit;
回滚段roll_abc 被指定给这个 delete 事务,commit 命令则在事务结束之后取
消了回滚段的指定.
7.数据库重建应注意的问题
在利用import进行数据库重建过程中,有些视图可能会带来问题,因为结构输
入的顺序可能造成视图的输入先于它低层次表的输入,这样建立视图就会失败.要
解决这一问题,可采取分两步走的方法:首先输入结构,然后输入数据.命令举例如
下 (uesrname:jfcl,password:hfjf,hoststing:ora1,数据文件:expdata.dmp):
impjfcl/hfjf@ora1 file=empdata.dmp rows=N
impjfcl/hfjf@ora1 file=empdata.dmp full=Y buffer=64000
commit=Yignore=Y
第一条命令输入所有数据库结构,但无记录.第二次输入结构和数据,64000 字
节提交一次.ignore=Y选项保证第二次输入既使对象存在的情况下也能成功.
select a.empnofrom emp a where a.empno not in (select empno from emp1 where
job=’SALE’);
倘若利用外部联接,改写命令如下:
select a.empnofrom emp a ,emp1 b
wherea.empno=b.empno(+)
and b.empno isnull
andb.job=’SALE’;
可以发现,运行速度明显提高.
8.从已知表新建另一个表:
CREATE TABLEb
AS SELECT * (可以是表 a 中的几列)
FROM a
WHERE a.column= ...;
9.查找、删除重复记录:
法一: 用Group by 语句 此查找很快的 第23页
selectcount(num), max(name) from student --查找表中num列重复的,列出重复
的记录数,并列出他的name 属性
group bynum
havingcount(num) >1 --按 num分组后找出表中num列重复, 即出现次数大于一
次
delete fromstudent(上面 Select 的)
这样的话就把所有重复的都删除了。-----慎重
法二:当表比较大(例如 10 万条以上)时,这个方法的效率之差令人无法忍受,需要
另想办法:
---- 执行下面SQL语句后就可以显示所有DRAWING和DSNO相同且重复的记
录
SELECT * FROMEM5_PIPE_PREFAB
WHEREROWID!=(SELECT MAX(ROWID) FROM EM5_PIPE_PREFAB D --D
相当于 First,Second
WHEREEM5_PIPE_PREFAB.DRAWING=D.DRAWING AND
EM5_PIPE_PREFAB.DSNO=D.DSNO);
---- 执行下面SQL语句后就可以刪除所有DRAWING和DSNO相同且重复的记
录
DELETE FROMEM5_PIPE_PREFAB
WHEREROWID!=(SELECT MAX(ROWID) FROM EM5_PIPE_PREFAB D
WHERE EM5_PIPE_PREF
AB.DRAWING=D.DRAWINGAND
EM5_PIPE_PREFAB.DSNO=D.DSNO);
10.返回表中[N,M]条记录:
取得某列中第 N大的行
selectcolumn_name from
(selecttable_name.*,dense_rank() over (order by column desc) rank from
table_name)
where rank =&N;
假如要返回前5 条记录:
select * from tablename where rownum<6;(或是 rownum <= 5 或是
rownum !=6)
假如要返回第 5-9 条记录:
select * fromtablename
where … 第24页
andrownum<10
minus
select * fromtablename
where …
andrownum<5
order byname
选出结果后用 name 排序显示结果。(先选再排序)
注意:只能用以上符号(<、<=、!=)。
select * fromtablename where rownum != 10;返回的是前9条记录。
不能用:>,>=,=,Between...and。由于 rownum是一个总是从1 开始的伪列,Oracle
认为这种条件 不成立,查不到记录.
另外,这个方法更快:
select * from(
select rownumr,a from yourtable
where rownum<= 20
order by name)
where r >10
这样取出第 11-20 条记录!(先选再排序再选)
要先排序再选则须用 select 嵌套:内层排序外层选。
rownum是随着结果集生成的,一旦生成,就不会变化了;同时,生成的结果是依
次递加的,没有1 就永远不会有2!
rownum 是在 查询集合产生的过程中产生的伪列,并且如果 where 条件中存在
rownum 条件的话,则:
1: 假如 判定条件是常量,则:
只能 rownum = 1, <= 大于1 的自然数, = 大于 1 的数是没有结果的, 大于一
个数也是没有结果的
即 当出现一个 rownum 不满足条件的时候则 查询结束 this isstop key!
2: 当判定值不是常量的时候
若条件是 = var , 则只有当 var 为1 的时候才满足条件,这个时候不存在 stop
key ,必须进行 full scan ,对每个满足其他where 条件的数据进行判定
选出一行后才能去选 rownum=2的行……
11.快速编译所有视图
---- 当在把数据库倒入到新的服务器上后(数据库重建),需要将视图重新编译一
遍,因为该表空间视图到其它表空间的表的连接会出现问题,可以利用 PL/SQL
的语言特性,快速编译。
SQL >SPOOLON.SQL
SQL >SELECT ‘ALTER VIEW ‘||TNAME||’ 第25页
COMPILE;’ FROMTAB;
SQL >SPOOLOFF
然后执行 ON.SQL即可。
SQL>@ON.SQL
当然,授权和创建同义词也可以快速进行,如:
SQL >SELECT‘GRANT SELECT ON ’
||TNAME||’ TOUSERNAME;’ FROM TAB;
SQL >SELECT‘CREATE SYNONYM
‘||TNAME||’ FOR USERNAME.’||TNAME||’;’ FROMTAB;
12.读写文本型操作系统文件
---- 在 PL/SQL 3.3以上的版本中,UTL_FILE包允许用户通过 PL/SQL读写操作
系统文件。如下:
DECALRE
FILE_HANDLEUTL_FILE.FILE_TYPE;
BEGIN
FILE_HANDLE:=UTL_FILE.FOPEN(
‘C:/’,’TEST.TXT’,’A’);
UTL_FILE.PUT_LINE(FILE_HANDLE,’
HELLO,IT’S ATEST TXT FILE’);
UTL_FILE.FCLOSE(FILE_HANDLE);
END;
13.在数据库触发器中使用列的新值与旧值
---- 在数据库触发器中几乎总是要使用触发器基表的列值,如果某条语句需要某
列修改前的值,使用:OLD 就可以了,使用某列修改后的新值,用:NEW 就可以
了。如:OLD.DEPT_NO,:NEW.DEPT_NO。
14.数据库文件的移动方法
当想将数据库文件移动到另外一个目录下时,可以用 ALTER DATABASE 命令
来移动(比ALTER TABLESPACE适用性强):
1. 使用SERVER MANAGER关闭实例.
SVRMGR >connect internal;
SVRMGR >shutdown;
SVRMGR>exit;
2. 使用操作系统命令来移动数据库文件位置(假设这里操作系统为 SOLARIS 第26页
2.6). 在UNIX中用 mv命令可以把文件移动到新的位置,
#mv/ora13/orarun/document.dbf /ora12/orarun
3. 装载数据库并用alter database命令来改变数据库中的文件名.
SVRMGR >connect internal;
SVRMGR >startup mount RUN73;
SVRMGR >alter database rename file
> ‘/ ora13/orarun/document.dbf’
> ‘/ora12/orarun/document.dbf’;
4. 启动实例.
SVRMGR >alter database open;
15.连接查询结果:
表 a 列 a1a2
记录 1 a
1 b
2 x
2 y
2 z
用 select 能选成以下结果:
1 ab
2 xyz
下面有两个例子:
1.使用 pl/sql 代码实现,但要求你组合后的长度不能超出 oracle varchar2 长度的
限制
create orreplace type strings_table is table of varchar2(20);
/
create orreplace function merge (pv in strings_table) return varchar2
is
lsvarchar2(4000);
begin
for i in1..pv.count loop
ls := ls ||pv(i);
end loop;
return ls;
end;
/
create table t(id number,name varchar2(10));
insert into tvalues(1,'Joan');
insert into tvalues(1,'Jack'); 第27页
insert into tvalues(1,'Tom');
insert into tvalues(2,'Rose');
insert into tvalues(2,'Jenny');
column namesformat a80;
selectt0.id,merge(cast(multiset(select name from t where t.id = t0.id) as
strings_table))names
from (selectdistinct id from t) t0;
drop typestrings_table;
drop functionmerge;
drop tablet;
2.纯粹用 sql:
表 dept, emp
要得到如下结果
deptno, dname,employees
---------------------------------
10, accounting,clark;king;miller
20, research,smith;adams;ford;scott;jones
30, sales,allen;blake;martin;james;turners
每个 dept的employee 串起来作为一条记录返回
This exampleuses a max of 6, and would need more cut n pasting to do more than
that:
SQL> selectdeptno, dname, emps
2 from (
3 selectd.deptno, d.dname, rtrim(e.ename ||', '||
4lead(e.ename,1) over (partition by d.deptno
5 order bye.ename) ||', '||
6lead(e.ename,2) over (partition by d.deptno
7 order bye.ename) ||', '||
8lead(e.ename,3) over (partition by d.deptno
9 order bye.ename) ||', '||
10lead(e.ename,4) over (partition by d.deptno
11 order bye.ename) ||', '||
12lead(e.ename,5) over (partition by d.deptno
13 order bye.ename),', ') emps,
14 row_number() over (partition by d.deptno
15 order bye.ename) x
16 from emp e, deptd
17 whered.deptno = e.deptno
18 )
19 where x =1
20 /
DEPTNO DNAMEEMPS 第28页
------------------ ------------------------------------------
10 ACCOUNTINGCLARK, KING, MILLER
20 RESEARCHADAMS, FORD, JONES, ROONEY, SCOTT, SMITH
30 SALES ALLEN,BLAKE, JAMES, MARTIN, TURNER, WARD
16.在 Oracle中建一个编号会自动增加的字段,以利于查询
1、建立序列:
CREATE SEQUENCEcheckup_no_seq
NOCYCLE
MAXVALUE9999999999
START WITH2;
2、建立触发器:
CREATE ORREPLACE TRIGGER set_checkup_no
BEFORE INSERTON checkup_history
FOR EACHROW
DECLARE
next_checkup_noNUMBER;
BEGIN
--Get the nextcheckup number from the sequence
SELECTcheckup_no_seq.NEXTVAL
INTO next_checkup_no
FROM dual;
--use thesequence number as the primary key
--for therecord being inserted
:new.checkup_no:= next_checkup_no;
END;
17.查看对象的依赖关系(比如视图与表的引用)
查看视图:dba_dependencies 记录了相关的依赖关系
查东西不知道要查看哪个视图时,可以在DBA_Objects里看,
selectobject_name from dba_objects where object_name like '%ROLE%'(假如查看
ROLE相关)
然后 DESC 一下就大体上知道了。 第29页
18.要找到某月中所有周五的具体日期
selectto_char(t.d,'YY-MM-DD') from (
select trunc(sysdate,'MM')+rownum-1 as d
fromdba_objects
where rownum< 32) t
whereto_char(t.d, 'MM') = to_char(sysdate, 'MM') --找出当前月份的周五的日期
andtrim(to_char(t.d, 'Day')) = '星期五'
--------
03-05-02
03-05-09
03-05-16
03-05-23
03-05-30
如果把 where to_char(t.d, 'MM') =to_char(sysdate, 'MM')改成sysdate-90,即为查
找当前月份的前三个月中的每周五的日期。
1.4.1. 建立用户
用户名: oracle
密码: oracle
sqlplus '/assysdba'
echo$ORACLE_SID
create usernanjing identified by nanjing;
grantconnect,resource,create session,create table to nanjing;
2. 数据字典的使用
1.表:
select * from cat; //显示所有用户对象。
select * from tab; //显示所有用户表。
select table_name from user_tables; //显示所有用户表 第30页
2.视图:
select textfrom user_views where view_name=upper('&view_name');
//显示某个视图
3.索引:
selectindex_name,table_owner,table_name,tablespace_name,status from
user_indexesorder by table_name;
//显示用户索引
4.触发器:
selecttrigger_name,trigger_type,table_owner,table_name,status fromuser_triggers;
//显示用户触发器
5.快照:
selectowner,name,master,table_name,last_refresh,next from user_snapshots
order byowner,next;
6.同义词:
select * from syn;
7.序列:
select * from seq;
8.数据库链路:
select * from user_db_links; 第31页
9.约束限制:
select
TABLE_NAME,CONSTRAINT_NAME,SEARCH_CONDITION,STATUS
from user_constraints WHERETABLE_name=upper('&TABLE_Name');
10.本用户读取其他用户对象的权限:
select * from user_tab_privs;
11.本用户所拥有的系统权限:
select * from user_sys_privs;
12.用户:
select * from all_users order byuser_id;
13.表空间剩余自由空间情况:
select tablespace_name,sum(bytes) 总字节数,max(bytes),count(*) from
dba_free_spacegroup by tablespace_name;
14.数据字典:
selecttable_name from dict order by table_name;
可以通过数据字典表查询 其他系统表
selecttable_name from dict where table_name = ‘ ***%’order by table_name
15.锁及资源信息:
select * from v$lock;不包括 DDL锁 第32页
16.数据库字符集:
selectname,value$ from props$ where name='NLS_CHARACTERSET';
simplifiedchiniese_china.zhs16GBK 简体中午编码
17.inin.ora 参数:
select name,value from v$parameter order byname;
18.SQL 共享池:
select sql_text from v$sqlarea;
19.数据库:
select * from v$database
20.控制文件:
select * from V$controlfile;
21.重做日志文件信息:
select * from V$logfile;
22.来自控制文件中的日志文件信息:
select * from V$log;
23.来自控制文件中的数据文件信息:
select * from V$datafile; 第33页
24.NLS 参数当前值:
select * from V$nls_parameters;
25.ORACLE 版本信息:
select * from v$version;
26.描述后台进程:
select * from v$bgprocess;
27.查看版本信息:
select * fromproduct_component_version;
28.查询 oracle 中所有用户信息
select * from dba_users;
29.只查询用户和密码
select username,password fromdba_users;
30.查询当前用户信息
select * from dba_ustats;
3. PL/SQL 语言
ProcedureLanguage Structure Qurrey Language――PL/SQL 第34页
3.1. Oracle的变量类型
数据类型
数字,字符,布尔,日期
组合类型
Record(不同数据集合),table(一张表),varray(数组)
参考型
Ref cursor, ref object_type
数字类型
Binary_integer,Dec,Float
Number
Number(3)
Number(4,3) 前面的总长,后面是小数的长度
字符类型
Char(不可变长),varchar(过时) , varchar2(现在使用) , string
Boolean,date
Declare
V_firstName varchar(20);
Declare
V_firstName students.first_name%type; ――和students.first_name 的大小一
致
*显示输出―――set serveroutput on
3.2. 代码注释
多行 /* */
单行 --
3.3. Type关键字:
Example 1:
Declare
V_id students.id%type:=1;
V_name students.name%type:=’mudi’;
V_age students.age%type:=24;
Begin
Dbms_ouput.put_line(v_id);
Dbms_output.put_line(v_name);
Dbms_output.put_line(v_age);
End; 第35页
DECLARE
v_LastName S_EMP.LAST_NAME%TYPE;
v_FirstName S_EMP.FIRST_NAME%TYPE;
v_ID S_EMP.ID%TYPE;
Example 2:
BEGIN
select ID,LAST_NAME,FIRST_NAME INTO v_ID,v_LastName,v_FirstName
FROM S_EMPWHERE rownum = 1;
DBMS_OUTPUT.PUT_LINE(v_ID);
DBMS_OUTPUT.PUT_LINE(v_LastName);
DBMS_OUTPUT.PUT_LINE(v_FirstName);
END;
多个 TYPE 类型组合使用
DECLARE
v_LastName S_EMP.LAST_NAME%TYPE;
v_FirstName S_EMP.FIRST_NAME%TYPE;
v_ID S_EMP.ID%TYPE;
BEGIN
select ID,LAST_NAME,FIRST_NAME INTO v_ID,v_LastName,v_FirstName
FROM S_EMPWHERE rownum = 1;
DBMS_OUTPUT.PUT_LINE(v_ID);
DBMS_OUTPUT.PUT_LINE(v_LastName);
DBMS_OUTPUT.PUT_LINE(v_FirstName);
END;
3.4. record组合类型(相当于 C中的结构体)
Example 1:
Type class isrecord(
Id students.id%type;
Name students.name%type;
Age studnets.age%type;
);
Sd0510 class;
Begin
Select * into sd0510 from classes whereclass_name=’sd0510’;
Dbms_output.put_line(sd0510.id);
End;
Example 2:
Declare
Type emp_type is record(
Emp_id s_emp.id%type, 第36页
Emp_first_name s_emp.first_name%type,
Emp_last_name s_emp.last_name%type
)
Emp emp_type;
Begin
Select * into emp from s_emp where id=1;
Dbms_output.put_line(emp.emp_id);
End;
3.5. Rowtype类型
Example 1:
declare
Emps_emp%rowtype;
Begin
Select * into emp from s_emp where id=1;
End;
Table 类型
Example 1:
Declare
Type t_emp is table of s_emp%rowtype index bybinary_integer;
Emp t_emp;
Begin
Select * into emp(100) from s_emp where id =100;
dbms_output.put_line('id===>'||emp(100).id);
dbms_output.put_line('first_name===>'||emp(100).first_name);
dbms_output.put_line('last_name===>'||emp(100).last_name);
end;
3.6. TABLE类型
TYPE Info ISTABLE OF S_EMP%ROWTYPE INDEX BY BINARY_INTEGER;
v_info Info;
3.7. 变量的作用域与可见性
如同 JAVA 第37页
3.8. 控制语句
IF 判断语句
JAVA
If(logicexpression){}
Else if(logicexpression){}
Else{}
PL/SQL
If logicexpression then ….
Elsif logicexpression then
Endif
Example 1:
declare
i number;
begin
select count(*) into i from s_emp;
if i=0 then
dbms_output.put_line('no elements ins_emp');
elsif i<10 then
dbms_output.put_line('number < 10');
else
dbms_output.put_line(i);
end if;
end;
Loop 表达式
Loop
If logic_expression then exit;
End loop;
While 表达式
While logic
…
End loop;
For 表达式(与JAVA 的特点是)
For j in low..high loop
….
End loop;
GOTO语句
特点:只能从内部跳到外部
NULL语句
解决一些空语句的问题
Example 1:
If … then
… 第38页
Else
Null;
End if;
Example 2:
If … then
…
Goto goto_end;
End;
<<goto_end>>
End;
3.9. SQL in PL/SQL
DataManipulation language
Data Definitionlanguage
TransationControl
System comment
ESQL
在 PL/SQL只能使用 DML,TransationControl
3.10. Cursor 的使用
声明 Cursor s is select * from s_emp;
打开 Open s;
提取数据 FETCH S INTO emp;
EXIT WHEN S%NOTFOUND;
Cursor 的关键字
Found
Notfound
Isopen
Rowcount
在 loop 中使用cursor
declare
cursor emp_cur is select * from s_emp;
emp s_emp%rowtype;
begin
loop
fetch emp_cur into emp;
if emp_cur%notfound then
exit;
end if; 第39页
end loop;
close emp_cur;
end;
/
在 while中使用cursor
Open emp_cur;
Whileemp_cur%found loop
Fetch emp_cur into emp;
Dbms_output.put_line(emp.id);
End loop;
Close emp_cur;
在 for 中使用cursor
open emp_cur;
for emp inemp_cur loop
dbms_output.put_line(emp.id);
end loop;
close emp_cur;
3.11. 异常的使用
异常分为:
系统异常
Dup_val_on_index
Timeout_on_resource
……
自定义异常
Example 1:
DECLARE
myException EXCEPTION;
F_NAME S_EMP.FIRST_NAME%TYPE;
F1_NAME S_EMP.FIRST_NAME%TYPE;
CURSOR S IS SELECT FIRST_NAME FROM S_EMP;
BEGIN
OPEN S;
LOOP
FETCH S INTO F_NAME;
EXIT WHEN S%NOTFOUND;
IF F_NAME IS NULL THEN
RAISE myException;
ELSE
DBMS_OUTPUT.PUT_LINE(' F_Name : ' ||F_NAME);
END IF; 第40页
END LOOP;
CLOSE S;
select first_name into f1_name froms_emp;
DBMS_OUTPUT.PUT_LINE(' F1_Name : ' ||F1_NAME);
EXCEPTION
WHEN myException THEN
DBMS_OUTPUT.PUT_LINE(' Captured !');
CLOSE S;
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE(' Captured NO DATAFOUND!');
END;
注意:for emp in emp_cur loop …..end loop;自动关闭cursor
3.12. 使用 PROCEDURE
行参模式分为 in, out , int out 默认为 in
CREATE ORREPLACE PROCEDURE ModeTest(
p_In IN NUMBER,
p_Out OUT NUMBER,
p_inout IN OUT NUMBER)
IS
v_Local Number;
BEGIN
v_Local := p_In;
p_Out := 7;
p_InOut := 7;
END ModeTest;
/
注意: 如果在 SQLPLUS里看详细的信息,show errors
In 模式形参可以有默认值 DEFAULT 或者 :=
两种命名方法
名字标识法:
Test_procedure(outPara=>a,intPara=>b,inoutPara=>c);
outPara ,intPara , inoutPara 为行参名字
位置标识法:
Test_procedure(a,b,c);
注意:要想直接在sqlplus运行procedure 第41页
Variable anumber;
Variable bnumber;
Exectest_procedure(inpara=>100,outpara=>2);
输出结果
以上命令只能用在SQLPLUS的 CONSOLE
匿名块每次都编译,有名块第一次编译,以后不用。
删除 PROCEDURE : drop procedure_name
3.13. 使用 FUNCTION
3.13.1. 程序分两种:
1.通过create or replace 编译的存在数据库里
2.没有 create or replace 不存在数据库里
且只能被调用的父过程调用。
CREATE ORREPLACE FUNCTION lessthen_test(
src IN NUMBER,
ref IN NUMBER := 400)
RETURN BOOLEANAS
BEGIN
IF src > ref THEN RETURN FALSE;
ELSE RETURN TRUE;
END IF;
END;
3.14. PACKAGE
3.14.1. 包的声明
CREATE ORREPLACE PACKAGE MyPackages IS
PROCEDURE AddStudent(
p_ID IN S_EMP.ID%TYPE,
p_FNAME IN S_EMP.FIRST_NAME%TYPE := '',
p_LNAME IN S_EMP.LAST_NAME%TYPE DEFAULT ''
);
FUNCTION DeleteStudent(
p_ID IN S_EMP.ID%TYPE 第42页
) RETURN BOOLEAN;
END MyPackages;
3.14.2. 包的定义
CREATE ORREPLACE PACKAGE BODY MyPackages AS
PROCEDURE AddStudent(
p_ID IN S_EMP.ID%TYPE,
p_FNAME IN S_EMP.FIRST_NAME%TYPE := '',
p_LNAME IN S_EMP.LAST_NAME%TYPE DEFAULT ''
) IS
Duplicate EXCEPTION;
i NUMBER := 0;
BEGIN
SELECT COUNT(*) INTO i FROM S_EMP WHERE ID= p_ID AND
FIRST_NAME =p_FNAME AND LAST_NAME = p_LNAME;
IF i = 0 THEN
INSERT INTO S_EMP (ID,FIRST_NAME,LAST_NAME)
VALUES(p_ID,p_FNAME,p_LNAME);
COMMIT;
ELSE
RAISE Duplicate;
END IF;
EXCEPTION
WHEN Duplicate THEN
DBMS_OUTPUT.PUT_LINE('Duplicate Record');
END AddStudent;
FUNCTION DeleteStudent(
p_ID IN S_EMP.ID%TYPE
) RETURN BOOLEAN IS
i NUMBER := 0;
BEGIN
SELECT COUNT(*) INTO i FROM S_EMP WHERE ID= p_ID;
IF i > 0 THEN
DELETE FROM S_EMP WHERE ID = p_ID;
COMMIT;
ELSE
NULL;
END IF;
RETURN TRUE;
END DeleteStudent; 第43页
END;
3.14.3. 包的初始化代码
3.15. 触发器
CREATE ORREPLACE TRIGGER qiuTrigger after DELETE OR INSERT OR
UPDATE ON S_EMP
FOR EACH ROW(行触发器,不写为语句触发器)
DECLARE
i NUMBER := 0;
BEGIN
SELECT COUNT(*) INTO i FROM S_EMP
DBMS_OUTPUT.PUT_LINE(' Only ' || i || 'Student(s) left.');
END;
三种触发条件
两种触发时间
两种触发规则 (每行或每语句)
不能有事务语句
不能在正在修改的表
不可以修改任何变化表(定义触发器的表);
3.16. Pl/sql 中执行动态 SQL DDL语句
Executeimmediate test_sql ;
使用占位符合
(:1)
Using id;
* clear screem
- Oracle笔记
- Oracle笔记
- oracle笔记
- Oracle 笔记!
- oracle笔记
- oracle 笔记
- ORACLE笔记
- oracle笔记
- ORACLE笔记
- oracle 笔记
- oracle笔记
- Oracle笔记
- Oracle笔记
- oracle笔记
- oracle笔记
- oracle 笔记
- Oracle 笔记
- oracle 笔记
- Unix学习之——文件安全性
- 传智播客--AJAX知识点和实用练习总结
- Hibernate 笔记
- EJB 笔记
- UNIX学习之——基本文件处理
- Oracle 笔记
- static和const关键字尽可能多的作用
- 怎么使用CTreeListCtrl
- 与其做痛苦的房奴,不如做个快乐的租房族
- 关于浏览器缓存数据处理
- jQuery的三种“$()”
- rcp,erp,ide,SDK
- c++ 笔记,自备
- [轉] 加密全世界GSM手機的密碼被破解了