Oralce学习笔记(4)

1.数据字典

1.1简介

Oracle数据库中的表包括用户所定义的表及oracle系统所产生的表,两种类型。

数据字典表:描述数据库相关信息,运行状态,有多个用户,每个用户有哪些表,表的结构是什么,表空间,系统权限,角色。Oracle运行相关的数据均存在数据字典表中。执行DDL语句均会对数据字典表的内容产生变化。 (基表---视图)。

 

数据字典表大部分属于SYS这个帐户。

 

1.2命名规则

数据字典表的前缀:

USER     用户自己的

ALL 用户可以访问到的

DBA       管理员视图

V$   性能相关的数据

 

select * from user_tables 查询出当前用户所拥有的所有表

select * from all_tables 查询可以访问到所有表

select * from dba_tables 查询系统中所有的表

 

C、DICTIONARY存放了所有字典表

 

select * from DICTIONARY;

 

 

(2)、常用的字典表

select * from user_objects;

select * from USER_TAB_COLUMNS;--查表的列定义信息

select * from USER_TAB_COLUMNS wheretable_name='EMP';

select * from USER_CONSTRAINTS;

select * from USER_CONS_COLUMNS wheretable_name='EMP';

select * from user_views;

select * from user_sequences;

select * from user_synonyms;

select * from DBA_TAB_PRIVS;--对象权限

select count(*) from DBA_SYS_PRIVS;---系统权限

2. 方案schema

方案是一个用户所拥有的所有数据库对象及其它资源的集合。

hr.emp==>访问hr这个方案的emp对象。

每创建一个用户,就会立即创建与这个用户同名的方案。用户名与方案名是一对一关系。

3.数据导入导出及数据库维护

操作系统命令:exp导出数据

            imp导入数据

 exp-help

 imp-help

导出:

exp scott/test tables=(emp,dept) log=(f:\test\emp.log)file=(f:\test\emp.dump)

 

导出某几个用户下所有数据:

exp scott/test owner=(scott,test)log=(f:\test\emp.log) file=(f:\test\emp.dump)

导入:

 impscott/test file=(f:\test\emp.dump)

 

跨用户导入:

imp system/test fromuser=(scott)touser=(test) file=(f:\test\dept.dmp)

host imp system/test fromuser=scotttouser=test file=(f:\test\dept.dmp)

4.闪回(falshback)

4.1概述

传统恢复数据库的方法,靠备份。(备份定期进行,每天1次,全备份,增量备份),数据库大时非常不方便,消耗很多时间。效率都非常差。

恢复数据是对正确及错误数据打包处理。

 

oracle 9i推出回收站的功能,10g,11g以后功能更加强大。可以通过数据使用命令快速恢复数据。闪回不依赖于备份,系统会自动根据操作日志来完成恢复。

闪回只对错误的数据进行处理。

 

闪回应用场景

错误删除数据commit,如何找回?

错误删除表,如何找回?

如何获得表中的历史记录?

如何撤销一个错误的事务(多个dml语句)

4.2闪回技术支持

1)闪回的类型

A、闪回表,把表回退到过去的一个时间上;(flashback table)

B、闪回删除:回收站;(flashbackdrop)

C、闪回版本查询(重点是查询):通过select获取历史记录;所有提交的历史记录。(flashback versionquery)

D、闪回事务查询:通过undo_sql撤销事务。(flashback transaction query)

E、闪回次数据库;把数据库回退到过去的一个时间上。

F、闪回归档日志

 

2)闪回的语法

FLASHBACK TABLE [schema.]<table_name>

TO 

{[BEFORE DROP [RENAME TO table]] 

[SCN|TIMESTAMP]expr

[ENABLE|DISABLE]TRIGGERS}

 

3)闪回表

把表回退到过去的一个时间上(或者系统改变号上).

 

SCN--系统改变号。

select timestamp_to_scn(sysdate)from dual;查询某一时间对应的系统改变号。

授权scott执行闪回表

grant flashback any table to scott;

闪回表的语法:

flashback table 表名 to scn 1182535;

flashback table 表名 to TIMESTAMP to_date('...');

没有启用行移动功能,不能闪回表。

启动行移动:

alter table flashback_table enable rowmovement;

alter table t1 enable row movement;

执行闪回

flashback table t1 to scn 1182535;

 

4)闪回删除(回收站)

闪回删除-回收站(只有普通用户才有回收站)。

 

命令:flashbacktable 表名 to beforedrop [rename to 新表];  表名可以是要闪回表的真实名字,也可以是在回收站中的名字。

 

回收站操作:

show recyclebin 显示回收站内容

purge recyclebin 清空回收站内容

删除表的时候指定不要放到回收站

drop tabel test purge;(不在回收站中的表无法闪回)

 

使用回收站中表名称来闪回表

flashback table"BIN$PkH2wA+WTZO6DCzCn9ryew==$0" to before drop;

 

闪回删除,并把闪回的表进行改名

flashback table dept1 to before drop renameto dept2;

 

5)闪回版本查询--查询(select),(flashback version query)

获得对一张表的操作完整的过程。

 

select cname from table_name versionsbetween scn 111 and 7777.

查看以前的数据。

 

select vid,content  from version_table versions between timestampminvalue and maxvalue;

 

查询操作时间的伪列

versions_operation,versions_starttime,versions_endtime,versions_xid(事务ID)

 

selectvid,content,versions_operation,versions_starttime,versions_endtime  from version_table versions between timestampminvalue and maxvalue

 

6)闪回事务查询

如果想要取消某一个事务.就需要通过flashback_transaction_query这个视图中获得这个取消该事务的sql语句(undo_sql).

要查询某一个事务的undo_sql,就需要获得事务xid,通过ersions_xi伪列可以查。

 

SQL> selectversions_operation,versions_starttime,versions_xid,deptno,dname,loc from dept1versions

between scn minvalue and maxvalue;

查询un_sql

select undo_sql fromflashback_transaction_query where xid='070001005A010000'

执行查询到的undo_sql。

查询事务版本需要权限:selectany transaction

5. PL/SQL编程基础

5.1概述

PL/SQL(Procedure Language/SQL)

PLSQL是Oracle对sql语言的过程化扩展

指在SQL命令语言中增加了过程处理语句(如分支、循环等),使SQL语言具有过程处理能力。

5.2PL/SQL语法

declare

     说明部分    (变量说明,光标申明,例外说明〕

begin

     语句序列   (DML语句〕…

exception

     例外处理语句  

end;

简单例子:

set serveroutput on

declare 

--声明变量

v_name varchar2(50);--普通变量

v_sal number(6) :=5000;--声明变量并指定默认值

v_job emp.job%TYPE;--变量的类型与emp表中的job字段相同,引用型变量

v_job1 v_job%TYPE default 'hello';--引用

v_date date;

begin

--给变量赋值1

v_date :=sysdate;

dbms_output.put_line(v_date);

--给变量赋值2,从表中查询数据并赋给变量

select job into v_job from emp where empno=7369;

dbms_output.put_line(v_job);

--同时给多个变量赋值

select job,ename into v_job1,v_name fromemp where empno=7499;

dbms_output.put_line(v_name||':'||v_job1);

end;

5.3记录类型变量

set serveroutput on

declare 

--声明变量

v_r emp%ROWTYPE;--记录型变量,v_r可以存emp表的一行记录

v_name emp.ename%TYPE;

begin

--给记录型变量赋值

select * into v_r from emp whereempno=7369;

v_name:=v_r.ename;

dbms_output.put_line('员工姓名:'||v_name||',工资'||v_r.sal);

end;

5.4 if和循环语句

if语句:

set serveroutput on

--通过accept(SQLPLUS命令)接收键盘输入

--num:地址

accept num prompt '请输入一个数字';

declare 

--声明变量,&num变量引用内存地址

v_num number :=&num;

begin

--使用if来判断0,大于0,还是小于0

if v_num>0 then

dbms_output.put_line('大于0');

elsif v_num<0 then

dbms_output.put_line('小于0');

else

dbms_output.put_line('等于0');

end if;

end;

循环语句(3种方式):

set serveroutput on

declare 

--声明变量,&num变量引用内存地址

v_num number :=10;

v_i number;

begin

--循环输出1到v_num

--while循环1

v_i:=1;

while(v_i<=v_num) loop

dbms_output.put_line(v_i);

v_i:=v_i+1;

end loop;

dbms_output.put_line('循环1结束........');

--循环2loop...end looop

v_i:=1;

loop

dbms_output.put_line(v_i);

v_i:=v_i+1;

/*

if(v_i>10) then

exit;

end if;*/

exit when v_i>10;

end loop;

dbms_output.put_line('循环2结束........');

 

--循环3,for  in loop end loop

for v_i in 1..v_num loop

dbms_output.put_line(v_i);

end loop;

dbms_output.put_line('循环3结束........');

end;

--dbms_output.put(v_i);不换行

 

输出99表:

set serveroutput on

declare 

--声明变量

v_i number;

v_j number;

begin

--输出9*9表

--dbms_output.put(v_i);不换行

for v_i in 1..9 loop

for v_j in 1..v_i loop

dbms_output.put(v_j||'*'||v_i||'='||(v_i*v_j)||'');

end loop;

dbms_output.put_line('');

end loop;

end;

6.游标CURSOR

1)声明游标

CURSOR 光标名  [ (参数名  数据类型[,参数名数据类型]...)]

     IS  SELECT   语句

普通游标:

CURSOR c_emp is select * from emp wheredeptno=20;

 

带参数游标:

CURSOR c_emp(v_deptno) is select * from emp where deptno=v_deptno;

 

2)在程序中使用游标

打开游标

 openc_emp;

取一行光标的值:fetchc_emp into  r_emp;

读值

fetch c_emp into  r_emp;

 

关闭光标 closec_emp;

 

读取游标属性:

%ISOPEN 是否已经打开

%NOTFOUND 找不到数据

%FOUND 是否找到数据

%ROWCOUNT 当前取到第几条

访问c_emp游标的%ROWCOUNT值:c_emp%ROWCOUNT

 

3)普通游标示例

declare 

--声明变量

--声明游标

CURSOR c_emp is select * from emp wheredeptno=20;

v_r emp%ROWTYPE;

begin

--打开游标

open c_emp;

--从游标取值

loop

fetch c_emp into v_r;

--如果取不到数据则退出

exit when c_emp%NOTFOUND;

--读值

dbms_output.put_line(c_emp%ROWCOUNT||':'||v_r.ename||'='||v_r.sal);

end loop;

--关闭光标

close c_emp;

end;

 

4)带参数的游标示例:

declare 

--声明变量

--声明带参数的游标

CURSOR c_emp(v_deptno number) is select *from emp where deptno=v_deptno;

v_r emp%ROWTYPE;

begin

--打开带参数的游标,要讲参数传进去

open c_emp(20);

--从游标取值

loop

fetch c_emp into v_r;

--如果取不到数据则退出

exit when c_emp%NOTFOUND;

--读值

dbms_output.put_line(c_emp%ROWCOUNT||':'||v_r.ename||'='||v_r.sal);

end loop;

--关闭光标

close c_emp;

end;

7.例外、异常

1)语法

begin

--程序体

exception

when 异常1 then

...

when 异常2 then

...

when others then

处理其它异常的代码

2)系统自定义的异常

No_data_found

Too_many_rows

Zero_Divide

Value_error

Timeout_on_resource

3)处理普通异常示例

set serveroutput on

--给员工涨工资的程序引入存储过程,如果员工职位是经理,涨20%,如果销售,15%,其它涨10%,总的可以涨的工资总额不能超过2000元。

declare 

--声明变量

v_sal emp.sal%TYPE;

begin

dbms_output.put_line(5/0);--

select sal into v_sal from emp wheredeptno=20;

dbms_output.put_line('工资:'||v_sal);

 

exception

when Too_many_rows then

dbms_output.put_line('数据太多!');

when others then

dbms_output.put_line('其它异常!');

end;

4)自定义异常

声明异常

  not_data exception;

程序体,抛出异常:

 raise not_data

处理异常

exception

  when not_data then

5) 自定义异常示例

set serveroutput on

accept num prompt '请输入';

declare 

--声明变量

v_num number:=&num;

e_errorData exception;

begin

 

if(v_num=0) then

--抛出异常:

raise e_errorData;

end if;

dbms_output.put_line('正确的数字:'||v_num);

 

exception

--处理异常

when e_errorData then

dbms_output.put_line('数据不能为0!');

when others then

dbms_output.put_line('其它异常!');

end;

8.存储过程及函数

8.1概述

指存储在数据库中供所有用户程序调用的子程序(基于pl/sql语法写出来程序)叫存储过程、存储函数。

 

为什么要用存储过程:

A、提升性能

B、安全性考虑

C、把复杂的业务放到存储过程。便于dba管理。

 

存储过程不好的地方:

代码不好维护;不容易扩展。

存储过程和存储函数的区别:

存储过程可以有返回值也可以没有返回值,存储函数必须有返回值。

8.2存储过程的使用

1)创建存储过程

create [or replace] PROCEDURE 过程名(参数列表)  AS

--声明变量

begin

--程序体

exception

 

end [过程名];

 

2)示例(涨工资)

CREATE OR REPLACE PROCEDURE RAISESALARY

(

 V_DEPTNO IN EMP.DEPTNO%TYPE 

, V_RATE IN NUMBER default 0.1

) AS

--声明变量

BEGIN

update emp set sal=sal*(1+v_rate) wheredeptno=v_deptno;

---加更多更好业务逻辑

END RAISESALARY;

 

3)调用存储过程

exec[ute] raisesalary(20,0.2);

call raisesalary(20,0.2);

8.3存储函数的使用

 

1)创建存储函数

 

CREATE [OR REPLACE] FUNCTION 函数名(参数列表)

 RETURN  函数值类型

AS

 

begin

 

return 返回值;

 

exception

 

end 函数名;

 

2)示例(获得某一个部门的平均工资)

 

CREATE OR REPLACE FUNCTION GETDEPTAVGSAL

(

 V_DEPTNO IN EMP.DEPTNO%TYPE 

) RETURN EMP.SAL%TYPE AS

--声明变量

v_sal emp.sal%TYPE;

 

BEGIN

 select avg(sal) into v_sal from emp where deptno=V_DEPTNO;

 RETURN v_sal;

END GETDEPTAVGSAL;

 

3)调用存储函数

查询语句里面调:

select getdeptavgsal(20) from dual;

可以在其它存储过程及函数中调用。

9.触发器

9.1概述

数据库触发器是一个与表相关联的、存储的PL/SQL程序。每当一个特定的数据操作语句(Insert,update,delete)在指定的表上发出时,Oracle自动地执行触发器中定义的语句序列。

 

触发器的类型:

语句级触发器

在指定的操作语句操作之前或之后执行一次,不管这条语句影响了多少行。

行级触发器(FOR EACHROW):

触发语句作用的每一条记录都被触发。在行级触发器中使用old和new伪记录变量, 识别值的状态。

触发器是一段pl/sql程序,程序是存储在数据库中。调用不是由用户来调用。会在特定的条件下自动执行。

 

执行dml语句时候,他可能运行。

相当在后台设置监控程序,满足运行即运行。触发器。

9.2创建触发器

CREATE [or REPLACE] TRIGGER  触发器名

 

 {BEFORE | AFTER}

  {DELETE | INSERT | UPDATE [OF 列名]}

  

 ON  表名

  

[FOR EACH ROW [WHEN(条件) ] ]

 

being

 PLSQL 块

end;

9.3示例

create or replace trigger mytest

before insert

on emp

declare

--声明变量

begin

 

dbms_output.put_line('准备插入数据!');

if(to_char(sysdate,'yyyy')='2012') then

 raise_application_error(-20003,'2012世界末时,不用操作数据!');

end if;

end;

 

当执行往emp中insert数据时,会引上面的触发器运行。

SQL> insert into emp(empno,ename)values(999,'aaa');

准备插入数据!

insert into emp(empno,ename)values(999,'aaa')

           *

第 1 行出现错误:

ORA-20003: 2012世界末时,不用操作数据!

ORA-06512: 在 "SCOTT.MYTEST", line 7

ORA-04088: 触发器 'SCOTT.MYTEST' 执行过程中出错

10. Java中调用存储过程及函数

publicclass OracleTest {

      @Test

      publicvoid callProcedure() throws Exception{

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

           Stringurl="jdbc:oracle:thin:127.0.0.1:1521:orcl";

           Connectionconn= DriverManager.getConnection(url, "scott","test");

           CallableStatementstmt=null;

           try{

           //调用存储过程的语法

           //Statement/PreparedStatement/CallableStatement

            stmt= conn.prepareCall("{callRAISESALARY(?,?)}");

           //设置参数

           stmt.setObject(1,20);

           stmt.setObject(2,0.2);

           //调用

           stmt.execute();

           }

           catch(Exception e){

                 e.printStackTrace();

           }

           finally{

                 if(stmt!=null)stmt.close();

                 if(conn!=null)conn.close();

           }

      }

      @Test

      publicvoid callFunction() throws Exception{

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

           Stringurl="jdbc:oracle:thin:127.0.0.1:1521:orcl";

           Connectionconn= DriverManager.getConnection(url, "scott","test");

           CallableStatementstmt=null;

           try{

                 //方式1

           //调用存储函数的语法{?=call GETDEPTAVGSAL(?)}

           //Statement/PreparedStatement/CallableStatement

            stmt= conn.prepareCall("{?=callGETDEPTAVGSAL(?)}");

            //设置参数

            //如果是数据库端传回来的参数,则要注册为输出型参数

            stmt.registerOutParameter(1,OracleTypes.NUMBER );

           stmt.setObject(2,20);

           //调用

           stmt.execute();

           //读取结果

           System.out.println("结果:"+stmt.getDouble(1));

           //方式2

           //使用sql语句函数

           //函数中不能有dml语句

           ResultSetrs= conn.createStatement().executeQuery("selectGETDEPTAVGSAL(20) from dual");

           if(rs.next()){

                 System.out.println(rs.getObject(1));

           }

           rs.close();

           }

           catch(Exception e){

                 e.printStackTrace();

           }

           finally{

                 if(stmt!=null)stmt.close();

                 if(conn!=null)conn.close();

           }

      }

}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Oracle是一种关系型数据库管理系统,广泛用于企业级应用程序中。学习Oracle需要全面了解其结构、基本概念和操作技巧。 首先,了解Oracle数据库的体系结构非常重要。Oracle数据库由实例和数据库组成。实例是数据库在内存中的运行实体,数据库是磁盘上存储数据的地方。了解实例和数据库之间的关系以及它们各自的功能对于后续学习非常重要。 其次,掌握SQL语言对于学习Oracle至关重要。SQL是结构化查询语言的缩写,用于与数据库进行交互。学习SQL语言,包括基本的SELECT、INSERT、UPDATE和DELETE语句,以及高级的聚合函数、连接查询和子查询等操作,可以帮助我们有效地访问和操作Oracle数据库。 此外,熟悉Oracle数据库的基本概念也是学习的关键。如表、视图、索引、约束、触发器等一系列数据库对象的使用和管理,以及事务的概念和ACID特性的重要性等。 了解Oracle的性能调优也是学习Oracle的必备知识之一。通过优化查询、索引和存储结构等手段来提高数据库的性能可以使数据库系统更加高效地运行。 最后,了解Oracle的高级特性和功能也是学习的重点。如分区表、数据泵、分布式数据库、备份和恢复等高级功能,在复杂的企业级环境中能够更好地应对各种需求。 总之,学习Oracle需要综合掌握数据库的结构、SQL语言、基本概念、性能调优和高级特性等。通过理论学习和实践操作相结合,逐步积累经验,才能够成为熟练的Oracle数据库管理员或开发人员。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值