Oracle学习笔记
desc animal_ty;
查看 user_types;
user_type_attrs;
二,抽象数据类型的使用
1)创建关系表
drop table animal;
create table animal
(id number primary key ,
anima animal_ty
);
set desc depth 3
desc animal;
2) 插入数据(使用构造方法)
insert into animal values(1, animal_ty('MULE','FRANCES','PLAY'));
insert into animal values(2, animal_ty('DOG','BENJI','EAT'));
insert into animal values(3, animal_ty('CROCODILE','LYLE','SWIM'));
3)操作
查看:select f.anima.name from animal f;
更新: update animal f set f.anima.hobby='PLAY1' where id=1;
删除:delete from animal a where a.anima.hobby='PLAY1';
2,删除对象类型
drop type animal_ty force;
3,查询相关性
select name,type from user_dependencies where referenced_name='ANIMAL_TY';
4,在抽象数据类型上创建索引
create index Idx on animal(anima.name);
5,final 和 not final 修饰类型
instantiable 和not instantiable 可修饰类型和方法
默认情况下,抽象数据类型是不能被继承的,同时类型提供构造函数,类型中的方法可以被实
现
声明类型加 not final 该类型可被继承
修饰方法: not instantiable 类型不提供方法实现
修饰类型: not instantiable 类型没有构造函数.不能实例化
二,可变数组
1)创建VARRAY类型
create or replace type tools_va as varray(5) of varchar2(25);
2)创建关系表,该表的字段类型是varray类型
create table borrower(name varchar2(25) primary key,
tools tools_va);
字典
select typecode,attributes from user_types where type_name='TOOLS_VA';
select coll_type,elem_type_owner,elem_type_name,upper_bound,
length from user_coll_types;
3)插入数据
insert into borrower values ('JED HOPKINS',
Tools_va('HAMMER','SLEDGE','AX'));
insert into borrower values('PK',
Tools_va('PEN1','PEN2','PEN3'));
4)查看
select * from table(select t.tools from borrower t where t.name='PK');
三,嵌套表
drop type emp_ty force;
1,
create or replace type emp_ty as object
( empno number,
ename char(10),
sal number);
2,create or replace type emps_nt as table of emp_ty;
3,
create table ntdept
(
deptno number,
dname varchar2(20),
loc varchar2(20),
dno_det emps_nt)
nested table dno_det store as emp_nt_tab;
--插入数据
insert into ntdept values
(10,'市场部','海珠北路',emps_nt(emp_ty(100,'MARRY',1000),
emp_ty(101,'Lili',1500),
emp_ty(102,'KHK',3000))
);
insert into ntdept values(20,'教务部','海珠南路',emps_nt(emp_ty(103,'JAKE',2200),
emp_ty(104,'ROSE',1000),
emp_ty(105,'LUSU',2000)
));
--查询
可以使用the或table
select deptno,dname,loc,dno_det from ntdept;
select dno_det from ntdept where deptno=10;
select nt.* from table(select dno_det from ntdept where deptno=10) nt;
select nt.* from table(select dno_det from ntdept where deptno=20) nt where
nt.empno=103 ;
select nt.empno,nt.ename from table(select deptno from ntdept where deptno=10)
nt where nt.empno=101;
--插入
insert into table(select dno_det from ntdept where deptno=10)
values(106,'HANG',3000);
或从嵌套表中选择数据插入
insert into ntdept values(40,'NEWd','NEWloc',
cast(multiset(select * from table(select dno_det from ntdept where deptno=10)
nt where nt.empno=100 ) as emps_nt))
cast:将查询的结果转换成嵌套表的形式
multiset:允许cast查询中包含多条记录
--更新
update table(select dno_det from ntdept where deptno=10) nt set nt.ename='LLLL'
where nt.empno=101;
--删除
delete from the(select dno_det from ntdept where deptno=10) nt where
nt.empno=101
四,对象表
1,建立对象类型
drop type animal_ty force;
create type animal_ty as object
(name varchar2(15),
hobby varchar2(20)
)
/
2,建立对象表
create table animal of animal_ty(name constraint pk primary key);
3,插入数据
insert into animal values(animal_ty('SNAKE','PLAY'));
insert into animal values(animal_ty('DOG','SWIM'));
insert into animal values(animal_ty('CAT','SLEEP'));
4,查看oid
select ref(f) from animal f;
5,查看对象
select value(r) from animal r;
使用deref
drop table keeper;
create table keeper
(
keepername varchar2(10),
animalkept ref animal_ty
)
插入数据
insert into keeper select 'JEK',ref(f) from animal f where name='DOG';
insert into keeper select 'BLK',ref(f) from animal f where name='CAT';
查看数据
在关系表中看对象
select deref(animalkept) from keeper;
假设删掉一个对象
delete from animal where name='DOG';
select * from keeper; 还在引用该对象
update keeper set animalkept=null where animalkept is dangling;--去掉引用
五,对象视图
将dept关系表做为对象表访问
1,建立对象类型
create or replace type dept_type as object
(dno number(2),
dname varchar2(15),
local varchar2(18)
);
2,建立对象视图
create view dept_view of dept_type with object oid
(dno) as
select * from dept ;
3,通过对象视图操纵关系表数据
insert into dept_view values(dept_type(60,'aaa','bbb'));
delete from dept_view where deptno=60;
结果会反映到关系表中,当改变关系表数据时,也会反映到对象视图中
对象视图每行都有一个oid
4,当关系表之间存在引用关系时,也可以用对象视图实现
dept 和 emp 是主、外键表,emp表的deptno引用了dept表的deptno
并且已为关系表dept生成了对象视图,此时关系表的每一个行都具有oid
dept表的行可以作为行对象通过dept_view视图进行访问,只要为关系表创建
了对象视图,即可将任何关系表作为行对象进行访问
--make_ref只对所提供的参数应用一个Oracle内部的算法,即可得到引用,它并没有真
正读取视图。
select make_ref(dept_view,deptno) from dept;
select make_ref(dept_view,deptno) from emp;
5,通过对象视图建立引用关系
create view emp_ov as select make_ref(dept_view,deptno) dep,empno,ename,sal
from emp;
该视图第一列指向了对象视图dept_view的行
select deref(a.dep) from emp_ov a;
在SQLPLUS下,实现中-英字符集转换
alter session set nls_language='AMERICAN';
alter session set nls_language='SIMPLIFIED CHINESE';
主要知识点:
一、有关表的操作
1)建表
create table test as select * from dept; --从已知表复制数据和结构
create table test as select * from dept where 1=2; --从已知表复制结构但不包括数据
2)插入数据:
insert into test select * from dept;
二、运算符
算术运算符:+ - * / 可以在select 语句中使用
连接运算符:|| select deptno|| dname from dept;
比较运算符:> >= = != < <= like between is null in
逻辑运算符:not and or
集合运算符: intersect ,union, union all, minus
要求:对应集合的列数和数据类型相同
查询中不能包含long 列
列的标签是第一个集合的标签
使用order by时,必须使用位置序号,不能使用列名
例:集合运算符的使用:
intersect ,union, union all, minus
select * from emp intersect select * from emp where deptno=10 ;
select * from emp minus select * from emp where deptno=10;
select * from emp where deptno=10 union select * from emp where deptno in (10,20); --不包括重复行
select * from emp where deptno=10 union all select * from emp where deptno in (10,20); --包括重复行
三,常用 ORACLE 函数
sysdate为系统日期 dual为虚表
一)日期函数[重点掌握前四个日期函数]
1,add_months[返回日期加(减)指定月份后(前)的日期]
select sysdate S1,add_months(sysdate,10) S2,
add_months(sysdate,5) S3 from dual;
2,last_day [返回该月最后一天的日期]
select last_day(sysdate) from dual;
3,months_between[返回日期之间的月份数]
select sysdate S1, months_between('1-4月-04',sysdate) S2,
months_between('1-4月-04','1-2月-04') S3 from dual
4,next_day(d,day): 返回下个星期的日期,day为1-7或星期日-星期六,1表示星期日
select sysdate S1,next_day(sysdate,1) S2,
next_day(sysdate,'星期日') S3 FROM DUAL
5,round[舍入到最接近的日期](day:舍入到最接近的星期日)
select sysdate S1,
round(sysdate) S2 ,
round(sysdate,'year') YEAR,
round(sysdate,'month') MONTH ,
round(sysdate,'day') DAY from dual
6,trunc[截断到最接近的日期]
select sysdate S1,
trunc(sysdate) S2,
trunc(sysdate,'year') YEAR,
trunc(sysdate,'month') MONTH ,
trunc(sysdate,'day') DAY from dual
7,返回日期列表中最晚日期
select greatest('01-1月-04','04-1月-04','10-2月-04') from dual
二)字符函数(可用于字面字符或数据库列)
1,字符串截取
select substr('abcdef',1,3) from dual
2,查找子串位置
select instr('abcfdgfdhd','fd') from dual
3,字符串连接
select 'HELLO'||'hello world' from dual;
4, 1)去掉字符串中的空格
select ltrim(' abc') s1,
rtrim('zhang ') s2,
trim(' zhang ') s3 from dual
2)去掉前导和后缀
select trim(leading 9 from 9998767999) s1,
trim(trailing 9 from 9998767999) s2,
trim(9 from 9998767999) s3 from dual;
5,返回字符串首字母的Ascii值
select ascii('a') from dual
6,返回ascii值对应的字母
select chr(97) from dual
7,计算字符串长度
select length('abcdef') from dual
8,initcap(首字母变大写) ,lower(变小写),upper(变大写)
select lower('ABC') s1,
upper('def') s2,
initcap('efg') s3 from dual;
9,Replace
select replace('abc','b','xy') from dual;
10,translate
select translate('abc','b','xx') from dual; -- x是1位
11,lpad [左添充] rpad [右填充](用于控制输出格式)
select lpad('func',15,'=') s1, rpad('func',15,'-') s2 from dual;
select lpad(dname,14,'=') from dept;
12, decode[实现if ..then 逻辑]
select deptno,decode(deptno,10,'1',20,'2',30,'3','其他') from dept;
三)数字函数
1,取整函数(ceil 向上取整,floor 向下取整)
select ceil(66.6) N1,floor(66.6) N2 from dual;
2, 取幂(power) 和 求平方根(sqrt)
select power(3,2) N1,sqrt(9) N2 from dual;
3,求余
select mod(9,5) from dual;
4,返回固定小数位数 (round:四舍五入,trunc:直接截断)
select round(66.667,2) N1,trunc(66.667,2) N2 from dual;
5,返回值的符号(正数返回为1,负数为-1)
select sign(-32),sign(293) from dual;
四)转换函数
1,to_char()[将日期和数字类型转换成字符类型]
1) select to_char(sysdate) s1,
to_char(sysdate,'yyyy-mm-dd') s2,
to_char(sysdate,'yyyy') s3,
to_char(sysdate,'yyyy-mm-dd hh12:mi:ss') s4,
to_char(sysdate, 'hh24:mi:ss') s5,
to_char(sysdate,'DAY') s6 from dual;
2) select sal,to_char(sal,'$99999') n1,to_char(sal,'$99,999') n2 from emp
2, to_date()[将字符类型转换为日期类型]
insert into emp(empno,hiredate) values(8000,to_date('2004-10-10','yyyy-mm-dd'));
3, to_number() 转换为数字类型
select to_number(to_char(sysdate,'hh12')) from dual; //以数字显示的小时数
五)其他函数
user:
返回登录的用户名称
select user from dual;
vsize:
返回表达式所需的字节数
select vsize('HELLO') from dual;
nvl(ex1,ex2):
ex1值为空则返回ex2,否则返回该值本身ex1(常用)
例:如果雇员没有佣金,将显示0,否则显示佣金
select comm,nvl(comm,0) from emp;
nullif(ex1,ex2):
值相等返空,否则返回第一个值
例:如果工资和佣金相等,则显示空,否则显示工资
select nullif(sal,comm),sal,comm from emp;
coalesce:
返回列表中第一个非空表达式
select comm,sal,coalesce(comm,sal,sal*10) from emp;
nvl2(ex1,ex2,ex3) :
如果ex1不为空,显示ex2,否则显示ex3
如:查看有佣金的雇员姓名以及他们的佣金
select nvl2(comm,ename,') as HaveCommName,comm from emp;
六)分组函数
max min avg count sum
1,整个结果集是一个组
1) 求部门30 的最高工资,最低工资,平均工资,总人数,有工作的人数,工种数量及工资总和
select max(ename),max(sal),
min(ename),min(sal),
avg(sal),
count(*) ,count(job),count(distinct(job)) ,
sum(sal) from emp where deptno=30;
2, 带group by 和 having 的分组
1)按部门分组求最高工资,最低工资,总人数,有工作的人数,工种数量及工资总和
select deptno, max(ename),max(sal),
min(ename),min(sal),
avg(sal),
count(*) ,count(job),count(distinct(job)) ,
sum(sal) from emp group by deptno;
2)部门30的最高工资,最低工资,总人数,有工作的人数,工种数量及工资总和
select deptno, max(ename),max(sal),
min(ename),min(sal),
avg(sal),
count(*) ,count(job),count(distinct(job)) ,
sum(sal) from emp group by deptno having deptno=30;
3, stddev 返回一组值的标准偏差
select deptno,stddev(sal) from emp group by deptno;
variance 返回一组值的方差差
select deptno,variance(sal) from emp group by deptno;
4, 带有rollup和cube操作符的Group By
rollup 按分组的第一个列进行统计和最后的小计
cube 按分组的所有列的进行统计和最后的小计
select deptno,job ,sum(sal) from emp group by deptno,job;
select deptno,job ,sum(sal) from emp group by rollup(deptno,job);
cube 产生组内所有列的统计和最后的小计
select deptno,job ,sum(sal) from emp group by cube(deptno,job);
四、临时表
只在会话期间或在事务处理期间存在的表.
临时表在插入数据时,动态分配空间
create global temporary table temp_dept
(dno number,
dname varchar2(10))
on commit delete rows;
insert into temp_dept values(10,'ABC');
commit;
select * from temp_dept; --无数据显示,数据自动清除
on commit preserve rows:在会话期间表一直可以存在(保留数据)
on commit delete rows:事务结束清除数据(在事务结束时自动删除表的数据)
oracle命令
<FONT face=宋体 size=3>1.启动数据库
cd @ORACLE_HOME/bin
lsnrctl
start
2. @ORACLE_HOME/dbs目录下存放实例配置文件
3. 在java中以odbc方式连接oracle
1.配置sqlnet easy configration
2.在windows中配置odbc,添加 system DSN,其中data source name可任意指定,
sol*net connect string为在sol*net 中指定的Database alias
3.确保path指向orawin95\bin
4.执行oracle中的32-bit odbc test 测试连接
5. java中参数指定如下:
driver: "sun.jdbc.odbc.JdbcOdbcDriver",
dbURL: "jdbc:ODBC:odbc DSN 名",
logid: "",
logpass: ""
4. 在java中使用oracle 的 driver连接oracle
driver: "oracle.jdbc.driver.OracleDriver",
dbURL: "jdbc:oracle:thin:@机器名:1521:数据库",
logid: "",
logpass: "");
5. 设置日期格式
服务器端: export NLS_DATE_FORMAT='DD-MON_RR'
客户端: 进入win95注册表,选KEY_LOCAL_MACHINE->SOFTWARE->ORACLE,然后
从菜单选择编辑->新建->字符串值:输入NLS_DATE_FORMAT,然后编辑这个
新串,在值域输入DD_MON_RR(或RRRR)
6. 处理用户被锁住的方法
首先执行下列语句,确定用户是否真的被锁住:
select a.username,a.sid,a.serial#,b.id1,c.sql_text
from v$session a,v$lock b,v$sqltext c
where a.lockwait = b.kaddr
and a.sql_address = c.address
and a.sql_hash_value = c.hash_value;
USERNAME SID SERIAL# ID1 SQL_TEXT
--------- --- ----------- ---------
SCOTT 11 9 131080 update
plsql_user.s_employee
set salary=5000
结果SCOTT在做update时被锁住了
下一步确定是谁锁住了该用户,这个用户在做何种操作:
select a.username,a.sid,a.serial#,b.id1,c.sql_text
from v$session a,v$lock b,v$sqltext c
where b.id1 in
(select distinct e.id1
from v$session d,v$lock e
where d.lockwait=e.kaddr)
and a.sid = b.sid
and c.hashvalue=a.sql_hash_value
and b.request=0;
USERNAME SID SERIAL# ID1 SQL_TEXT
--------- --- ----------- ---------
PLSQL_USER 10 26 131080 update s_employee
set salary=10000
结果显示是由于PLSQL_USER和SCOTT对同一个表做update时将SCOTT锁住了
可以通过kill session释放锁,例如可以kill掉PLSQL_USER的session:
alter system kill session '10,26'
7. 使用查询优化器
Oracle Server提供了基于成本(Cost Based)和基于规则(Rule Based)
两种优化器,简称为CBO和RBO,用于查询操作的执行计划.可以使用下列
方法使用CB
方法1:在INIT<sid>.ORA文件中设置参数
OPTIMIZER_MODE=choose
方法2:在session级设置
OPTIMIZER_GOAL=FIRST_ROWS或ALL_ROWS
例如:
alter session set optimitzer_goal=first_rows
方法3:在查询中使用hint,包括:
CHOOSE,ALL_ROWS,FIRST_ROWS等
8. 确定某个查询使用了那一种优化器
使用EXPLAIN PLAN命令生成该查询语句的执行计划,然后检查PLAN_TABLE
表中POSITION字段,如果值为NULL,说明使用了Rule based优化器,否则表明
使用了Cost Based优化器:
select decode(nvl(position,-1),-1,'RBO','CBO')
from plan_table
where id=0;
9. 使用estimate方式对表进行分析
10. 建立一个与现存数据库相同,但不包含数据的空库
对全库作俄Export或Import时,使用参数ROWS=N
例:
exp system/manager full=Y rows=N file = full.dmp
imp system/manager full=Y rows=N file=full.dmp
11. 使某些host不能通过SQL*NETV2访问Oracle server
可以通过编辑$ORACLE_HOME/network/admin/protocol.ora文件完成
例如: protocol.ora
tcp.validnode_checking=yes
tcp.invited_nodes=(138.3.39.150)
这样只有138.3.39.150才能通过sol*netv2访问Oracle Server
又例如: protocol.ora
tcp.validnode_checking=yes
tcp.exclued_nodes=(138.3.39.150)
这样138.3.39.150被拒绝
12.在sol*plus中,向表中插入"'"
可以用chr(39)来标示"'"
例如:
insert into test values('i'||chr(39)||'m');
select * from test;
coll
---
i'm
13. 在win95或winNT上运行oracle Net8 Assistant 或 Net8 EasyConfguration
时报错"unhandled exception erro in java.exe"
oracle Net8 Assistant 或 Net8 EasyConfguration调用了java,而java
在win95或winNT上对系统的分辨率和颜色都有要求,应把系统的分辨率
调到大于640X480,颜色大于256但不能设置成true color
14. 安装oracle 8 for windows NT 需要NT的service pack 3
15. 在oracle7和oracle8之间export/import数据
必须先在oracle8数据库上以internal或sys用户运行catexp7.sql
svrmgr>connect internal
svrmgr>@?/rdbms/admin/catexp7.sql
16. 为远程用户设置"internal"口令
先在数据库端的init<sid>.ora文件中设置
remote_login_passwordfile=execlusive
并且为oracle owner设置环境变量
ORA_<SID>_PWFILE=orapw<sid>.pwd
然后以oracle owner 运行以下命令:
$cd $ORACLE_HOME/dbs
$orapwd file=orapw<sid>.pwd password=<passwd> entries=5
17. 手工安装sqlplus的help facility
以oracle用户运行以下命令
$cd $ORACLE_HOME/bin
$SYSTE system/manager;export SYSTEM_PASS
$helpins
18. 查出前台正在发出的sql语句
先查出正在运行的前台程序的sid:
sql>select sid,serial#,username,program
from v$session
where status='ACTIVE';
然后根据上面得到的sid,可查出正在运行的前台程序发出的sql语句:
sql>select user_name,sql_text
from v$open_cursor
where sid=xx;
19. 在数据库一级设置sql trace
在init.ora中加入参数sql_trace=true,然后重新启动
20. 在sql*plus中对某一session设置sql trace
sql*plus>alter session set sql_trace=true;
可以使用下列命令关闭trace
sql*plus>alter session set sql_trace=false;
21. 移动数据文件的位置
1. 正常关闭数据库
2. 复制文件到新位置
$cp $ORACLE_HOME/dbs/dbsNEW.DBF /usr3/oracle/db2NEW.dbf
3.svrmgrl
connect internal;
startup mount;
alter database rename file'<$ORACLE_HOME>/dbs/db2NEW.dbf'
to 'usr3/oracle/db2NEW.dbf';
alter database open
22. 移动LOG文件的位置
可以先添加新的LOG文件,再删除原来的LOG文件
svrmgrl>connect internal;
alter database add logfile
'<$ORACLE_HOME>/usr3/oracle/logNEW.dba';
alter database drop logfile
'<$ORACLE_HOME>/dbs/logNEW.dbf';
23. 确定安装了何种NETWORK DRIVER
使用'nm'命令,例如tcp/ip driver的符号为'nttini',要检查oracle是否
链接了该符号,可以利用下列命令:
nm oracle|grep nttini
如果nttini存在,表示rdbms已经链接了tcp/ip driver
24. 检查已安装的sql*net版本
可以在?/orainst目录下使用'inspdver'命令检查
$inspdver|grep SQL*NET
2.3.4.0.0 SQL*NEW(V2)
25. 备份数据库
把orant\database目录备份下来即可
26. 在unix下察看实例名
.pfofile文件 </FONT></P> <P ><FONT size=3><FONT face="Times New Roman"> <p></p></FONT></FONT></P>
Oracle学习笔记---(四)
在system用户中创建用户和授权:
create user usera identified by usera defalut tablespace test;
grant connect,resource to usera;
一,同义词
分私有和公共
私有:普通用户创建的,只有创建该同义词的用户才可以使用
前提:普通用户具有对scott用户的表emp具有访问权利
connect scott/tiger;
grant all on emp to usera; --all 包括:select ,update ,insert ,delete
connect usera/usera;
create synonym emp for scott.emp;
select * from emp;
公共:公共一般由dba创建,需要具有create public synonym 系统权限,如普通用户要创建需要
connect system/manager;
grant create public synonym to usera;
conect usera/usera;
create public synonym emp for scott.emp;
其他用户也可以使用公共同义词 emp
查看用户自己创建的同义词:user_synonyms
select synonym_name from user_synonyms;
二,序列
通常和表一起使用,用来生成唯一主键值,在插入数据时使用,但不属于任何表,独立于表存在
create sequence deptseq
increment by 10
start with 50
insert into dept values(deptseq.nextval,'Sale_dept','HaizhuStreet');
使用伪列nextval 和 currval
nextval:创建序列后第一次使用返回序列初始值,既start with指定的值,后续使用增量后的值
currval:返回序列的当前值
数据词典: user_sequences
三、视图
在创建视图时可以使用group by ,order by 子句,函数等,使用函数时需要指定列别名
1, 简单视图:使用单表查询创建的视图
可以对视图进行增删改操作,除了一些限定外,如:创建只读视图,或带有with chek option 选项的视图,或视图中不包含
基表中不允许为空的列(不允许向视图中插入数据)等
1)使用with check option 可以限定对单表视图的修改, 不能更新无法通过该视图查看的行
create or replace view emp_view as select * from emp where job='SALESMAN' with check option constraint empv;
SQL> select * from emp_view;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- ---------- ---------- ---------- ----------
7499 ALLEN SALESMAN 7698 20-2月 -81 1600 300 30
7521 WARD SALESMAN 7698 22-2月 -81 1250 500 30
7654 MARTIN SALESMAN 7698 28-9月 -81 1250 1400 30
7844 TURNER SALESMAN 7698 08-9月 -81 1500 0 30
update emp_view set job='CLERK' where empno=7499;将无法更新
如创建视图时没有with check option, 修改视图后将在视图查不到该行数据
2) 使用with read only 创建只读视图
create or replace view emp_view as select * from emp where job='SALESMAN' with read only;
3) 创建视图时使用force,强制创建视图
如果视图定义中引用了不存在的表或表中有不存在的列,或创建视图的所有者没有访问表的权限,都可以创建,
但创建的视图有错误,在稍后创建表或得到访问权限后,ORACLE自动重新编译使视图有效,可以手动编译
假设dept表也不存在a1列,但还可以创建视图,但会提示错误,在表dept添加列a1后,视图自动编译为有效
create or replace force view emp_view as select a1,dname from dept;
可以 使用 alter view emp_view compile ; 手动编译
2, 复杂视图 :
1)使用多表联接创建视图,
2)创建视图时包括函数或group by 等
复杂视图通常不能直接进行增删改,但对于使用多表联接创建的视图,可以使用INSTEAD OF 触发器可以修改(后面课程)
create or replace view emp_dept_view as select empno,ename,dname,emp.deptno
from dept,emp where dept.deptno=emp.deptno;
3, 键保留表
键保留表:复杂视图中出现的表。
如果满足条件:1) 主键列全部显示在视图中,并且它们的值在视图中都是唯一且非空的.
如: create or replace view emp_dept_view as
select empno,ename,dname,dept.deptno
from dept,emp where dept.deptno=emp.deptno;
empn是emp表的主键,并且它的值在emp_dept_view 中是唯一且非空.所以emp表是键保留表
而deptno的值在视图中不唯一,所以dept不是键保留表
可以 修改视图中键保留表中的数据,主键值除外
update emp_dept_view set ename='JOE' where empno=7566; //可以
update emp_dept_view set dname='abc' where deptno=30; //不行 dname是dept表中的列,dept不是键保留表
4,分区视图
create or replace view v_emp as select * from emp1 partition(p1) union all select * from emp1 partition(p2);
数据字典: user_views
使用方法:在SQL*PLUS下
col view_name for a10 --定制显示的列宽
col text for for a50
set linesize 200 --设置每行显示的字符数
select view_name,text from user_views; --查看用户创建的视图情况
四,索引
使用索引的目的:
1)强制唯一 :在primary key 列或UNIQUE 列上自动创建唯一索引
2)提高查询速度: 当查询使用索引时,速度会有戏剧性的提高
只有在查询中使用where 或 order by 时,才使用索引
1,唯一索引
create unique index ind2 on dept(deptno);
定义索引的列中,表的任意两行的值都不相同
2, 组合索引
在表的多列上创建的索引
create index comind1 on emp(deptno,empno)
3, 反向键索引
该索引反转索引列中的每一个字节
使插入操作分布在整个索引上,避免插入数据时索引性能的降低。但会使查询变慢
create index revind1 on salgrade(grade) reverse;
可将反向键索引改为标准索引
alter index revind1 rebuild noreverse;
4,位图索引(可在单个或多个连接表上创建)
如果列重复的次数超过了100次,则可以考虑在该列上建立位图索引。既不同值的数目比行数少的情况
表有1000000 行,某列有10000个不同值,可在该列上建立位图索引
在位图索引中,使用每个键值的位图,而不是使用rowid。位图中的每一位对应一个可能的rowid
映射函数
每位位置---------rowid(确定表的一行)
当where 子句中有and 或 or 条件时,可直接在位图上进行布尔运算
create bitmap index bitemp on emp(deptno);
5,索引组织表
对表是基于主键的访问,而不是基于rowid的访问
表中的数据象索引一样被存储,表中就没有rowid,因此用户不能从 索引组织表 中选取rowid伪列的值
对于要求精确匹配的查询和基于范围的搜索,它提供了一种更快的访问数据的方法
表的数据存储在与其关联的索引中,索引中不存储rowid ,而是存储表的实际数据
create table indorg (
a1 number(2) primary key,
a2 varchar2(10)
)
organization index;
用户不能在indorg表的其它列上创建索引,当数据很少变化时,使用索引组织表
6,基于函数的索引
如果在where 中某列上使用了函数,即使在列上创建了索引,索引也不会被使用。所以可以创建函数索引
create index exind1 on emp(length(ename)); --基于函数创建索引
create index exind2 on emp(sal+nvl(comm,0)); --基于表达式创建索引
7,键压缩索引
为了节省索引块的空间,相同的列值,作为前缀存储一次,后缀是不同的rowid
create index exind1 on emp(length(ename)) compress 1; --作为前缀处理的键列的数目为1
create index exind2 on emp(deptno) compress 1;
8,索引分区
当用户建立了分区表后,也可以在该表上创建索引,这个索引可以按照用于表分区同样值范围进行划分
create table emp1(
empno number(4),
ename varchar2(10),
job varchar2(9),
mgr number(4),
hiredate date,
sal number(7,2),
comm number(7,2),
deptno number(2))
partition by range(empno)
(
partition p1 values less than (7566),
partition p2 values less than (7900),
partition p3 values less than (maxvalue) )
1) 使用local 关键字,可以为每一个分区建立一个独立的索引,
这个索引命令将建立3个独立的索引,每个索引对应一个分区
数据字典:
select index_name,partition_name ,tablespace_name from user_ind_partitions
i) 本地无前缀索引
create index emp_ind1 on emp1(ename) local
ii) 本地前缀索引(索引的第一列与分区的第一列相同)
create index emp_ind1 on emp1(empno) local;
或 指定不同的索引表空间
create index emp_ind1 on emp1(empno) local
( partition p1 tablespace test1_idx,
partition p2 tablespace test2_idx,
partition p3 tablespace test3_idx)
如果分区上执行了修改,会自动重建索引
SQL> col segment_name for a20
SQL> select segment_name,partition_name,segment_type,tablespace_name from user_segments where segment_name='EMP_IND1';
SEGMENT_NAME PARTITION_NAME SEGMENT_TYPE TABLESPACE_NAME
-------------------- ------------------------------ ------------------ ------------------------------
EMP_IND1 P1 INDEX PARTITION SYSTEM
EMP_IND1 P2 INDEX PARTITION SYSTEM
EMP_IND1 P3 INDEX PARTITION SYSTEM
2) 使用global 关键字,创建全局索引
i) 全局无前缀索引
create index emp_ind2 on emp1(ename) global;
ii) 全局前缀索引
建立全局前缀索引(empno为前缀,不能使用ename做索引列)
create index emp_ind2 on emp1(empno,ename)
global
partition by range(empno)
(
partition p1 values less than (6000) ,
partition p2 values less than (7500) ,
partition p3 values less than (maxvalue)
)
对分区的任何操作都会使全局索引无效,需要重建索引
注释:不能手动删除索引分区,当所引用的数据从表分区中删除时,索引分区自动删除
五,簇
簇是一组表,由两个或多个拥有公共列的表组成
簇是用来存储表的方法,这些表相互联系密切并通常相连接在磁盘的相同区域上。
如:emp 表存储在磁盘的一个区域(section) 内,而dept表存储在另一区域内,它们的行可以被连接到同一区域上,该区域
称为簇(cluster),簇关键字通常是在查询中把表连接起来的一列或几列(如dept,emp中的deptno),要聚簇这些表,用户必须
是表的所有者
1,创建了空簇
create cluster emp_dept(deptno_key number(2));
创建了空簇(如同建表一样,也设置了空间)
2,下面创建包含在簇中的表
create table dept
(
deptno number(2) primary key,
dname char(14),
local char(13)
)
cluster emp_dept(deptno);
--deptno为表中将要存储在簇关键字deptno_key中的列名
create table emp
(
empno number(4),
ename varchar2(10),
job varchar2(9),
mgr number(4),
hiredate date,
sal number(7,2),
comm number(7,2),
deptno number(2) references dept
)
cluster emp_dept(deptno);
3, 建立簇索引(在向簇表插入数据之前建立簇索引)
create index emp_dept_NDX on cluster emp_dept;
4, 插入数据
insert into emp select * from scott.emp;
insert into dept select * from scott.dept;
两个表的数据实际存储在同一位置, 簇好象是包含两个表数据的一个大表
///////////////
Oracle学习笔记---(三)
三
一,锁
为了防止用户在同一时间并发地访问和修改资源,ORACLE使用不同类型的锁控制对数据的并发访问,以防止用户之间出现破坏性的交互操作
,oracle 为处理事务自动锁定资源。
锁在SQL语句开始它们与数据的相互作用时获得,并在事务的整个过程中有效
oracle9i使用两种锁模式:
.独占模式(排他):不允许其他任何并发会话以任何方式共享锁定的资源,修改数据时需要这种锁。
.共享模式:允许对同一块数据的并发读访问。在更改数据时,上升为独占模式
一)行级锁
insert update delete 隐式加行锁(排他)
select ... for update 显示加行锁(共享)
select ...for update 用于显示锁定将要更新的数据行,防止其他用户在更新之前操作此行
如:select * from emp where deptno=30 for update
update emp set ename='Joke' where empno=7499;
在锁释放之前,其他用户不可以对锁定的数据行进行(修改,删除)操作,查询可以
假如有其他用户要锁定同一资源:可以使用wait 子句对锁的等待时间控制
如: 在另一用户中:select * from emp where deptno=30 for update wait 2 (等待2秒 )
如2秒钟还未释放资源,系统将会给出提示信息
二)表级锁
共享模式(in share mode)
共享更新模式(in share update mode)
排他锁模式
锁定表的通用语法:
lock table 表名 in <share or share update or exclusive mode>;
1) 共享模式
不允许其他用户插入,更新和删除行,多个用户可以同时在同一表上设置共享锁,这样设置锁的多个用户都只能执行查询
lock table emp in share mode;
2)共享更新模式(in share update mode)
允许多个用户同时锁定表的不同行, 允许其他用户进行DML(insert update delete select)操作 , 除了已锁定的行
如: lock table emp in share update mode;
select * from emp where deptno=30 for update //锁定的行
其他用户不能delete ,update 部门30的雇员信息
其他用户可以查看锁定的行: select * from emp where deptno=30
3)排他锁模式(限制性强)
不允许其他用户插入,更新和删除行, 允许查看数据,但只有一个用户可以在表中放置排他锁
lock table emp in exclusive mode;
三) 死锁
如:USERA: lock table scott.emp in share mode;
USERB: lock table scott.emp in share mode ;
USERA: update scott.emp set ename='Smith' where empno=7369;
USERB: update scott.emp set job='CLERK' where empno=7521;
发生死锁
二,表分区
分区的类型:
1),范围分区: 分区基于某一特定列或一组列的值的范围
2),散列分区:数据基于hash 函数进行分区
3),复合分区:首先基于范围分区,然后使用HASH函数进一步划分为子分区
4), 列表分区:通过在每个分区的描述中指定分区键的离散值列表,
允许按自然方式对无序和不相关的数据集进行分组和组织
一)范围分区
1) 创建分区表(一列)
1,创建分区表(一列分区键empno)
create table emp1(
empno number(4),
ename varchar2(10),
job varchar2(9),
mgr number(4),
hiredate date,
sal number(7,2),
comm number(7,2),
deptno number(2))
partition by range(empno)
(partition p1 values less than (7566),
partition p2 values less than (7900),
partition p3 values less than (9999))
2,插入数据
insert into emp1 select * from scott.emp;
3,显示分区数据
select * from emp1 partition(p1); --分区键empno,小于7566的empno插入到p1分区
select * from emp1 partition(p2);
select * from emp1 partition(p3);
4,数据字典
col table_name for a15;
col partition_name for a15;
select table_name,partition_name from user_tab_partitions;
2)创建分区表(两列)
1, 创建分区表(两列deptno,empno)
create table emp2(
empno number(4),
ename varchar2(10),
job varchar2(9),
mgr number(4),
hiredate date,
sal number(7,2),
comm number(7,2),
deptno number(2))
partition by range(deptno,empno)
(partition om1 values less than (20,7566), --分区边界的左部分优先,当empno<7566时,deptno=20的记录也将被插入
partition om2 values less than (30,7900),
partition om3 values less than (maxvalue,maxvalue))
2, 插入数据
insert into emp2 select * from emp;
3, 显示分区数据
select * from emp2 partition(om1);
select * from emp2 partition(om2);
select * from emp2 partition(om3);
3) 按日期类型分区
create table emp3(
empno number(4),
ename varchar2(10),
job varchar2(9),
mgr number(4),
hiredate date,
sal number(7,2),
comm number(7,2),
deptno number(2))
partition by range(hiredate)
(partition om1 values less than (to_date('1980-12-31','yyyy-mm-dd')),
partition om2 values less than (to_date('1981-12-31','yyyy-mm-dd')),
partition om3 values less than (to_date('1982-12-31','yyyy-mm-dd')))
二)散列分区
使用hash 函数将数据划分到分区中
create table dept1(deptno number(2),
dname varchar2(14),
loc varchar2(13))
partition by hash(deptno)
(partition p1,partition p2);
insert into dept1 select * from scott.dept;
三)复合分区
create table salgrade1(grade number,losal number,hisal number)
partition by range(grade)
subpartition by hash(losal,hisal)
(
partition p1 values less than (3)
(subpartition sp1,subpartition sp2),
partition p2 values less than (6)
(subpartition sp3,subpartition sp4)
)
insert into salgrade1 select * from scott.salgrade;
select * from salgrade1 partition(p1);
select * from salgrade1 subpartition(sp1);
select * from salgrade1 subpartition(sp2);
四)列表分区
create table emp4
(empno number,
ename varchar2(10),
deptno number)
partition by list(deptno)
(
partition p1 values(10,20),
partition p2 values(30)
)
insert into emp4 select empno,ename,deptno from scott.emp;
select * from emp4 partition(p1);
三,维护分区
--表emp1在其用户所在的表空间中,创建用户时指定,没指定默认为系统表空间
1)在system用户中授权:
grant create tablespace to scott;
2)登录到scott用户
connect scott/tiger; --假设在服务器端,客户端要加连接字符串
3)创建表空间test,该表空间包含一个数据文件,大小是5M
create tablespace test datafile
'd:\ora1.dbf' size 5m;
1,移动分区
alter table emp1
move partition p1 tablespace test;--将分区移动到表空间test
2,添加分区
alter table emp3
add partition om4 values less than(to_date('1984-12-31','yyyy-mm-dd'));
3,删除分区
alter table emp3
drop partition om4;
4,结合分区--用于散列分区
使用散列方法分区的表中,可以将某个分区的内容分发到由hash函数确定的一个或多个分区中,然后清除选定的分区
alter table dept1 coalesce partition;
5,截断分区
删除分区的数据(不能回滚)
alter table emp3 truncate partition om3;
delete from emp3 partition(om1) //可以回滚
6, 拆分分区
原来的分区p2不存在了
--p21将包括:7566到7700的记录
--p22将包括:7701到7900的记录
alter table emp1 split partition p2 at(7700)
into(partition p21,partition p22);
7,合并分区
合并范围分区表中的相邻两个分区的内容,产生新的分区p2,原来的分区p21,p22不存在了
alter table emp1 merge partitions p21,p22 into partition p2;
8,交换表分区
非分区表的数据和已分区表的某个分区数据进行交换
要求:非分区表的结构要和已分区表相同
如:
1,建立分区表
create table Pdept(deptno number(2),
dname varchar2(14),
loc varchar2(13))
partition by range(deptno)
(partition p1 values less than (20) tablespace test, --指定分区所在的表空间
partition p2 values less than (maxvalue) tablespace test);
2,插入(分区表)数据
insert into Pdept select * from dept;
3,建立非分区表
create table Sdept as select * from dept where 1=2;
4,插入(非分区表)数据
insert into Sdept values(60,'MyDept','MyLoc');
5,交换分区
alter table Pdept exchange partition p2 with table Sdept;