打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
oracle 命令集合
Oracle 命令集合

1、  创建表空间:

create  tablespace 表空间名称  datafile  ‘文件地址以及文件名’  [ size ]  [ autoextend  [ on | off ] ];

       注:【 size 】 表示要创建的表空间的大小。单位可以为 K 或者 M。

    【 autoextend 】 表示创建的表空间是否为自动扩展类型。

2、  创建新用户:

create  user  用户名  identified  by  密码  [ default  tablespace  表空间名 ] [ temporary  tablespace  表空间名 ];

注:【default】 语句表示为新创建的用户分配一个默认的表空间;【tempporary】表示为新创建的用户提供一个临时的表空间。另外,如果创建数字账户,如 100、123 之类的登陆账户,那么需要将账户用双引号引起来例如:create  user  "101" indentified by  密码~~~~~~; 否则会出现“ORA-01935: 缺失用户或角色名”这样的异常。

3、  为新用户授予权限:

grant  connect  to  用户名;   表示授予用户连接数据库,创建表以及其他结构。

Grant  resource  to  用户名;  表示授予用户使用数据库空间的权限。

Grant  select | update  on  emp  to  用户名;

注:select 表示授予用户查询emp 表的权限,update 表示授予用户修改emp 表的权限。

4、  修改密码:

alter user  用户名 identified  by  新密码;

5、  删除用户:

drop  user  用户名  cascade ;

注:当用户拥有模式对象时必须使用 cascade;

6、  创建表:

create  table  表名称  (字段1  类型,字段2  类型,……..字段N  类型);

7、  修改表结构:

alter  table  表名称  madofy  (列名  类型,………);

表示修改表中的类型和字段的大小。

alter  table  表名称  add  (字段  类型,……..);

表示向表中添加新列。

Alter  table  表名称  drop  column  列名称;

表示删除表中的现有列。

8、  清除表中所有数据:

truncate  table  表名称;

truncate 命令和 delete  命令相似,都可以用于删除表中所有的记录,不同的是:truncate 命令表示删除表中所有记录并立即释放空间,而delete 则需要提交事务后才能释放空间,当确定数据无用时使用truncate 比使用delete 效率更高。

9、  查看表结构:

desc 表名称;

10、              删除表

drop  table  表名称;

11、              查询无重复列:

select  distinct  列名  from  表名;

12、              根据现有表创建新表:

create  table  新表名  as  select  *  from  旧表名;

注:改语句非常灵活,新表中的字段和数据根据查询语句而定。如: 可以将查询的 * 改为旧表中存在的列,可以在查询语句后添加where 条件以控制记录插入到新表。

13、              插入来自其他表的记录:

insert  into  表名A  select  *  from  表名B [ where  条件];

注:改语句要求表A要于表B具有相同的表结构。

14、              将表的操作权限授予给其他用户:

grant  select | delete | update  on  表名 to  用户名 [ whit  grant  option];

注:【with  grant  option】表示改授权用户可以将此权限授予其他用户。另外,改语句还可以只授予用户对某个表的某些列的修改权限,其语法如下:

grant  update (列名1 ,列名2~~~)  on  表名  to  用户名;

15、              撤销已授权用户的权限:

revoke  select | update | insert  on  表名  from  用户名;

16、              集合操作符:

a)         union 操作符用于返回两个查询选定的所有不重复的行。例如:

select  ID  from  表名1  union  select  ID  from 表名2;

b)        union  all  操作符用于返回两个查询选定的所有行。例如:

select  ID  from  表名1  union  all  select  ID  from 表名2;

c)        intersect  操作符用于只返回两个查询选都有的行。例如:

select  ID  from  表名1  intersect  select  ID  from 表名2;

d)        minus  操作符用于返回第一个表有的行而表二没有的行。例如:

select  ID  from  表名1  minus  select  ID  from 表名2;

17、              函数:

a)         日期函数:

详见书56~59页。

b)        字符函数:

详见书59~60页。

c)        数字函数:

详见书60~62页。

d)        其他函数:

详见书63~71页。

18、              表分区:

一般表的分区是在创建表的时候便已经完成。例如:

范围分区:

create  table  表名称

(

        ID  number(4),

        Name  char(20)

)

partition  by  range (列名)

(

        partition  分区名  values  luess  than  (分区边界值1)  [tablespace  表空间名],

        partition  分区名  values  luess  than  (分区边界值2)  [tablespace  表空间名],

        partition  分区名  values  luess  than  (分区边界值3)  [tablespace  表空间名],

partition  分区名  values  luess  than  (maxvalue)  [tablespace  表空间名]

);

散列分区:

partition  by  hash (列名)

(

        partition  分区名  [tablespace  表空间名],

        partition  分区名  [tablespace  表空间名],

        partition  分区名  [tablespace  表空间名],

partition  分区名  [tablespace  表空间名]

);

列表分区:

partition  by  list (列名)

(

        partition  分区名  values (‘匹配值’)  [tablespace  表空间名],

        partition  分区名  values (‘匹配值’)  [tablespace  表空间名],

        partition  分区名  values (‘匹配值’)  [tablespace  表空间名],

partition  分区名  values (‘匹配值’)  [tablespace  表空间名]

);

19、              分区的维护:(主要用于对已经创建的分区进行操作)

添加分区:

alter  table  表名称  add  partition  分区名称  values  less  than  (数字值);

注: 添加分区可以用于所有类型的表分区,其语法与对应的分区语法类似。

删除分区:

alter  table  表名称  drop  partition  分区名称;

注: 删除表分区的前提是必须创建了该分区,另外,在删除分区时,分区中的数据也会删除,所以在删除之前必须确定该分区中的数据已经没有存在的必要。

截断分区:截断分区的作用是删除分区中的所有记录。

   Alter  table  表名称  truncate  partition  分区名称;

合并分区:

alter  table  表名称  merge  partition  分区名称1,分区名称2  into  partition  新分区名称;

注: 合并分区可以将范围分区或复合分区表的两个相邻分区连接起来。结果分区将集成北合并的两个分区的较高上界。

拆分分区:

alter  table  表名称  split  partition  要分区的分区名称  at  (创建分区时的条件值) into(partition 新分区名称1,partition 新分区名称2);

注:拆分分区只可用于范围分区。另外也还可以重命名新分区。例如:

    alter  table  表名称  rename  partition  旧分区名称  to  新分区名称;

20、              表锁定:

行级锁:

select  *  from  表名称  where  条件  for  update  [ of  字段1,字段2,……];

注:该锁为行级锁,只对满足条件的指定的字段实行锁定。

表级锁:

loca  table  表名称  in  share  mode  [ nowait ];

注:【nowait】表示避免因为延迟的等待。该语句只对表实现共享锁,还有其他锁模式。请看书78页

21、              创建同义词:(所谓同义词就是对象的别名)

私有同义词:

create  [ or  replace ]  synonym  新建同义词名称  for  要创建同义词的对象名称;

注:私有同义词,顾名思义,旧时创建以后只能由该创建用户使用。创建它的前提条件是,用户必须具有对该表或其他结构的访问权限。

公有同义词:

create  [ or  replace ]  public  synonym  新建同义词名称  for  要创建同义词的对象名称;

注: 公有同义词对所有的用户都有效,但是创建它的前提条件是:用户必须是管理员的身份。另外当公有同义词和本地对象名称由重复时,本地对象优先。

22、              删除同义词:

drop  [ public ]  synonym  同义词名称;

注: 当要删除公有同义词时,用户页必须时管理员的身份。

23、              序列:(所谓序列,就是实现数据自动递增的种子)

a)         创建序列:

create  sequence  序列名称  

[ start  with  开始的序列号 ]

[ increment  by  序列号的间隔 ]

[ maxvalue  序列号的最大值 | nomaxvalue ]  -- 表示指定序列的最大值。Nomaxvalue 表示没有最大值。

[ minvalue  序列号的最小值 | nominvalue ]  -- 表示指定序列的最小值,它必须小于或等于start with 的值,并且小于 maxvalue。Nominvalue 表示没有最小值。

[ cycle | nocycle ];   -- 表示当序列到达最大或最小值时 是否从头开始

b)        访问序列:

序列名.nextval 表示获得序列的下一个值;――主要用于向表中插入记录。例如:

insert  into  表名称  values (序列名.nextval,~~~~~~~);

序列名.currval  表示获得序列的当前值;―― 主要用于查看。 例如:

select  aa.currval  from  dual;  

注: aa 为已经创建的序列,dual 是系统表。

c)        更改序列:

alter  sequence  序列名称  

[ increment  by  序列号的间隔 ]

[ maxvalue  序列号的最大值 | nomaxvalue ]  -- 表示指定序列的最大值。Nomaxvalue 表示没有最大值。

[ minvalue  序列号的最小值 | nominvalue ]  -- 表示指定序列的最小值,它必须小于或等于start with 的值,并且小于 maxvalue。Nominvalue 表示没有最小值。

[ cycle | nocycle ];  -- 表示当序列到达最大或最小值时 是否从头开始

注:不可以更改序列的start  with 的值。

d)        删除序列:

drop  sequence  序列名;

24、              视图:

a)         创建视图:

create  or  replace  view  视图名称  as  

select  表A.字段1,表A.字段2,……,表B.字段1,表B.字段2……

from  表A,表B  on  表A. 字段=表B.字段;

b)        删除视图:

drop  view  视图名称;

25、              索引:

a)         创建索引:

create  index  索引名称  on  表名称 (列名称)  [ tablespace  表空间名称];

注:索引还有其他多种类型,请参看书102-103页。

另外,如果指定多列,那么表示创建组合索引;

26、              游标的使用:

a)         动态游标:示例如下:

declare

    存储游标的变量 test_tab%rowtype;

--定义游标

cursor 游标名称 is select * from test_tab where 条件;  

begin

        open 游标名称;--打开游标

           loop – 对游标进行循环操作

              fetch 存储游标的变量  into 游标名称; --将游标的值赋给变量

              exit when 游标名称%notfound;  --结束循环的条件

              dbms_output.put_line (游标名称.字段名); --对赋值的变量操作

            end loop;

            close 游标名称;

    end;

b)        循环游标:(特点:可以直接对有表进行操作,不需要打开、显示赋值、显示判断结束的条件、关闭游标等)  建议使用改类型游标。示例如下:

declare

        cursor 游标名称 is select * from  cs_test where name='chenshan';  

begin

           for 变量 in 游标名称

            loop

               dbms_output.put_line(变量.字段名称);

           end loop;

end;

c)        ref 游标:(特点:可以在运行时才确定游标要执行的sql 语句,更加灵活)。其示例如下:

declare

       type temp is ref cursor;

       aa temp;

begin

     if 条件 then 

        open 游标名称 for select * from cs_test where 条件;

     elsif 条件 then

       open 游标名称 for select * from cs_goods where 条件;

     else

         open 游标名称 for select * from cs_test where 条件;

     end if;

     fetch 游标名称 into 存储游标的变量

     loop

         具体的操作;

     end loop;

     close 游标名称;

end;

27、              过程:

a)         创建过程:

create or replace procedure (参数列表) 

as

  --本地变量申明

begin

      --过程的主体操作

exception 

         when 条件 then 

              --错误处理;
end;

b)        :执行过程:

execute  过程名称 (参数列表);

注:过程

c)        :将执行过程的权限授予其他用户

grant  execute  on  过程名  to  用户名;

注:过程的调用不应该在sql 语句块中;

d)        :删除过程

drop  procedure  过程名;

28、              函数:

a)         :创建函数

create  [ or replace ] function function_name(parameter1,parameter2,......)—参数列表

return 要返回的数据类型

is | as

[ 本地变量声明 ];

begin

            【函数主体】;

exception

             when 条件(others)  then 

                【错误处理主体】 ;

end;

b)        :调用函数

可以为查询语句:

select  函数名称  from  dual;

也可以为pl / sql 语句块调用

begin

       。。。。。。。。。。。。

       调用函数;

       。。。。。。。。。。。。

end;

c)        将函数的使用权限授予其他用户:

grant  execute  on  函数名  to  用户名;

d)        删除函数:

drop  function  函数名称;

29、              程序包:

a)         程序包规范的创建:

create or replace package cs_manage_findindent as

       --声明函数

function func_addgoodds (goodstypeid  number , goodstypename varchar2) return  varchar2;

       --声明过程

       procedure 过程名称(参数);

       --声明游标

       cursor 游标名称(参数) return 返回的数据类型;

end;

b)        程序包主体的创建:

create  [ or  replace ]  package  body  程序包名称  is | as

       --下面是函数主体

function  func_addgoodds ( goodstypeid  number , goodstypename varchar2 ) 

return  varchar2  as

        begin

insert  into  cs_ProduceType  values ( goodstypeid , goodstypename );

           return '操作成功' ;

       exception 

               when others then

                   return '操作失败' ; 

       end ;

       --下面是过程主体

       procedure 过程名 (参数列表) as

        begin

           过程主体;--(pl/sql 语句块)

        exception

              when others then

                  错误主体;

        end;

       --下面是游标主体

cursor 游标名称 (参数列表) return 应该返回的数据类型(一般为表名称或者为 (表名称 % ROWTYPE) ) is  查询语句;

end;

注:程序包主要是用于包含过程,函数,游标等操作的集合,它的使用能够让pl/sql代码变得更加简洁、易懂,同时管理员管理起来也更加轻松。

程序包分为两个部分:一个为规范声明,另一个为程序包主体。顾名思义,规范声明是声明程序包中具体要实现的各种对象,而程序包主体则是具体实现规范声明中已经声明的各种对象。

程序保就好比是一本书,书的目录就相当于程序保的规范声明,而书中的章节内容就相当于是程序包的主体,它是对目录的一个实现。

30、              触发器:

a)         创建触发器:

create or replace trigger 触发器名称 

before | after [ delete | update | insert ]

on 表名称 

for each row 

begin

    --开始实现触发器的主体

insert into cs_test_temp values(:old.name,:old.age,:new.sex);

    dbms_output.put_line('已经启动了触发器!!!'); 

exception

        when others then 

             dbms_output.put_line('发现未知错误!!!'); 

end;

注:before | after 表示改触发器是在事件之前还是事件之后被触发。

[ delete | update | insert ]表示选择可以触发该触发器的事件。

for each row 表示对每一行的修改都会触发该触发器,即创建了一个行级触发器。

:old.name  表示事件之前name的值。

:new.sex   表示事件之后name的值。

31、              产生随机数字的语法:

num := dbms_random . random ;

32、              删除重复的记录:

delete from  表名称  where  id  in 

       ( select  id  from  表名称  group  by  id  having  count( * ) > 1) 

and 

          ( select  min( rowid )  from  表名称  group  by  id  having  count( * ) > 1) ;

注:group  by  关键字用于将不重复的字段全部列出,以及将重复的字段列出一个。 而having 则表示在group  by  语句后的条件关键字,因为在group  by  后面不能使用where条件关键字来使用条件语句。

33. 主键操作

–添加主键

alter table  tableName

add constraint  primaryKeyName  primary key(主键列名)

--删除主键

alter table  tableName

drop constraint  primaryKeyName  

 

查询锁定数据库的用户信息以及解除锁定

在Oracle中很多时候会出现用户被锁定的情况,该情况产生的原因很多,在此不做解释!主要讲一下查询被锁定的用户,以及解锁!首先,如出现锁定不能登陆的情况,那么首先需要使用拥有DBA权限的用户进行登陆(一般情况下能够登陆成功)接下来就是使用sql语句查询被锁定的用户!语句如下:

Select   username,account_status from dba_users;     

此时将会列出所有oracle用户名称以及该账户所处的状态,如果状态为:locked,那么表示该用户被锁定,是不能用此账户进行登陆的!解决的办法是解除锁定,如果为 chenshan 这个用户被锁定。示例语句如下:

alter user chenshan  account unlock;

解锁成功以后再次执行上面的查询语句,如果状态为 open,那么恭喜你,解锁成功!

 

Oracle导入/导出数据库的语法

oracle中除了在Oracle编辑器中用图形化的方式导入文理文件的数据方式外,还可以采用命令行的方式导入数据库,其语法实示例如下:                                                                                                                                                                               imp [username[/password[@service]]]   

步骤:1、首先在进入 dos, 然后切换到 oracle 数据库物理文件所在的目录即(dmp文件所在的目录)。接下来输入下述语句!

    imp username/password@service  file=psmis.dmp fromuser=psmis touser=psmis log=psmis.log 下面就语句的语法做一下解释:

imp :是导入数据库的语法前缀;

username/password@service :意思是登陆指定的service;

file :指的是已经分离的oracle数据库物理文件;

fromuser:指的是来源用户;

touser:指的是目标用户;

log:指的是当前目录下的日志文件;

-------------------以下是转载----------------

在 dos 中查看oracle中的imp,exp命令:
    imp help=y
    exp help=y
1.    导出表数据:
    文件名以backup_yyMMddHHmm.dmp 表示
    dateString=`date +%y%m%d%H%M`
    #echo $dateString
    su - oracle -c "exp userid/password tables=table1,table2 file= path/backup_$dateString.dmp BUFFER=8192 grants=y compress=N"
   compress:N表明导出来的文件不需要压缩放在一个数据块中,当数据库中的表数据特别大的时候,若放在不同的数据库,在恢复的时候会有问题。   
   导出的数据包括表创建语句,序列,触发器等。
2.    导入表数据
   表导入的过程:创建表,导入数据,创建序列
    echo backup file:$1
    fileName=$1
    echo $fileName
    #if [ "$fileName" = ""] 
    #then
    #   echo "请指定备份恢复的文件名,请指定绝对文件路径"
    #   exit 0;
    #fi
    #echo fileName=$fileName
    su - oracle -c "imp userid/password file=$fileName show=n buffer=2048000 ignore=Y commit=y grants=y full=y"
 
    ignore:Y表明忽略表创建的过程,只是将表中的数据导入表中。 

 

第二部分:

--如何在oracle中导入dmp数据库文件?
 2006/2/16 zhanghua first create                             

     Oracle数据导入导出imp/exp就相当于oracle数据还原与备份。exp命令可以把数据从远程数据库服务器导出到本地的dmp文件,imp命令可以把dmp文件从本地导入到远处的数据库服务器中。 利用这个功能可以构建两个相同的数据库,一个用来测试,一个用来正式使用。
 
执行环境:可以在SQLPLUS.EXE或者DOS(命令行)中执行,
 DOS中可以执行时由于 在oracle 8i 中  安装目录\ora81\BIN被设置为全局路径,
 该目录下有EXP.EXE与IMP.EXE文件被用来执行导入导出。
 oracle用java编写,SQLPLUS.EXE、EXP.EXE、IMP.EXE这两个文件有可能是被包装后的类文件。
 SQLPLUS.EXE调用EXP.EXE、IMP.EXE所包裹的类,完成导入导出功能。
 
下面介绍的是导入导出的实例。
数据导出:
 1 将数据库TEST完全导出,用户名system 密码manager 导出到D:\daochu.dmp中
   exp system/manager@TEST file=d:\daochu.dmp full=y
 2 将数据库中system用户与sys用户的表导出
   exp system/manager@TEST file=d:\daochu.dmp owner=(system,sys)
 3 将数据库中的表inner_notify、notify_staff_relat导出
    exp aichannel/aichannel@TESTDB2 file= d:\data\newsmgnt.dmp tables=(inner_notify,notify_staff_relat) 

 4 将数据库中的表table1中的字段filed1以"00"打头的数据导出
   exp system/manager@TEST file=d:\daochu.dmp tables=(table1) query=\" where filed1 like '00%'\"
  
  上面是常用的导出,对于压缩,既用winzip把dmp文件可以很好的压缩。
  也可以在上面命令后面 加上 compress=y 来实现。

数据的导入
 1 将D:\daochu.dmp 中的数据导入 TEST数据库中。
   imp system/manager@TEST  file=d:\daochu.dmp
   imp aichannel/aichannel@HUST full=y  file=file= d:\data\newsmgnt.dmp ignore=y 
   上面可能有点问题,因为有的表已经存在,然后它就报错,对该表就不进行导入。
   在后面加上 ignore=y 就可以了。
 2 将d:\daochu.dmp中的表table1 导入
 imp system/manager@TEST  file=d:\daochu.dmp  tables=(table1) 
 
 基本上上面的导入导出够用了。不少情况要先是将表彻底删除,然后导入。
 
注意:
 操作者要有足够的权限,权限不够它会提示。
 数据库时可以连上的。可以用tnsping TEST 来获得数据库TEST能否连上。

附录一:
 给用户增加导入数据权限的操作
 第一,启动sql*puls
 第二,以system/manager登陆
 第三,create user 用户名 IDENTIFIED BY 密码 (如果已经创建过用户,这步可以省略)
 第四,GRANT CREATE USER,DROP USER,ALTER USER ,CREATE ANY VIEW ,
   DROP ANY VIEW,EXP_FULL_DATABASE,IMP_FULL_DATABASE,
      DBA,CONNECT,RESOURCE,CREATE SESSION  TO 用户名字 
 第五, 运行-cmd-进入dmp文件所在的目录, 
      imp userid=system/manager full=y file=*.dmp
      或者 imp userid=system/manager full=y file=filename.dmp

 执行示例:
 F:\Work\Oracle_Data\backup>imp userid=test/test full=y file=inner_notify.dmp

屏幕显示
Import: Release 8.1.7.0.0 - Production on 星期四 2月 16 16:50:05 2006
(c) Copyright 2000 Oracle Corporation.  All rights reserved.

连接到: Oracle8i Enterprise Edition Release 8.1.7.0.0 - Production
With the Partitioning option
JServer Release 8.1.7.0.0 - Production

经由常规路径导出由EXPORT:V08.01.07创建的文件
已经完成ZHS16GBK字符集和ZHS16GBK NCHAR 字符集中的导入
导出服务器使用UTF8 NCHAR 字符集 (可能的ncharset转换)
. 正在将AICHANNEL的对象导入到 AICHANNEL
. . 正在导入表                  "INNER_NOTIFY"          4行被导入
准备启用约束条件...
成功终止导入,但出现警告。


附录二:
 Oracle 不允许直接改变表的拥有者, 利用Export/Import可以达到这一目的.
  先建立import9.par,
  然后,使用时命令如下:imp parfile=/filepath/import9.par
  例 import9.par 内容如下:
        FROMUSER=TGPMS        
        TOUSER=TGPMS2     (注:把表的拥有者由FROMUSER改为TOUSER,FROMUSER和TOUSER的用户可以不同)           
        ROWS=Y
        INDEXES=Y
        GRANTS=Y
        CONSTRAINTS=Y
        BUFFER=409600
        file==/backup/ctgpc_20030623.dmp
        log==/backup/import_20030623.log

 

34. 游标大全

1.Oracle游标大全
SELECT语句用于从数据库中查询数据,当在PL/SQL中使用SELECT语句时,要与INTO子句一起使用,查询的返回值被赋予INTO子句中的变量,变量的声明是在DELCARE中。SELECT INTO语法如下: 
SELECT [DISTICT|ALL]{*|column[,column,...]} 
INTO (variable[,variable,...] |record) 
FROM {table|(sub-query)}[alias] 
WHERE............ 
PL/SQL中SELECT语句只返回一行数据。如果超过一行数据,那么就要使用显式游标(对游标的讨论我们将在后面进行),INTO子句中要有与SELECT子句中相同列数量的变量。INTO子句中也可以是记录变量。 

%TYPE属性 
在PL/SQL中可以将变量和常量声明为内建或用户定义的数据类型,以引用一个列名,同时继承他的数据类型和大小。这种动态赋值方法是非常有用的,比如变量引用的列的数据类型和大小改变了,如果使用了%TYPE,那么用户就不必修改代码,否则就必须修改代码。 

例: 
v_empno SCOTT.EMP.EMPNO%TYPE; 
v_salary EMP.SALARY%TYPE; 
 不但列名可以使用%TYPE,而且变量、游标、记录,或声明的常量都可以使用%TYPE。这对于定义相同数据类型的变量非常有用。 
DELCARE 
V_A NUMBER(5):=10; 
V_B V_A%TYPE:=15; 
V_C V_A%TYPE; 
BEGIN 
DBMS_OUTPUT.PUT_LINE 
('V_A='||V_A||'V_B='||V_B||'V_C='||V_C); 
END 

SQL>/ 
V_A=10 V_B=15 V_C= 
PL/SQL procedure successfully completed. 
SQL> 

其他DML语句 
其它操作数据的DML语句是:INSERT、UPDATE、DELETE和LOCK TABLE,这些语句在PL/SQL中的语法与在SQL中的语法相同。我们在前面已经讨论过DML语句的使用这里就不再重复了。在DML语句中可以使用任何在DECLARE部分声明的变量,如果是嵌套块,那么要注意变量的作用范围。 

例: 
CREATE OR REPLACE PROCEDURE FIRE_EMPLOYEE (pempno in number) 
 AS 
v_ename EMP.ENAME%TYPE; 
BEGIN 
 SELECT ename INTO v_ename 
FROM emp 
WHERE empno=p_empno; 
INSERT INTO FORMER_EMP(EMPNO,ENAME) 
VALUES (p_empno,v_ename); 
DELETE FROM emp 
WHERE empno=p_empno; 
UPDATE former_emp 
SET date_deleted=SYSDATE 
WHERE empno=p_empno; 

EXCEPTION 
WHEN NO_DATA_FOUND THEN 
DBMS_OUTPUT.PUT_LINE('Employee Number Not Found!'); 
END 

DML语句的结果 
当执行一条DML语句后,DML语句的结果保存在四个游标属性中,这些属性用于控制程序流程或者了解程序的状态。当运行DML语句时,PL/SQL打开一个内建游标并处理结果,游标是维护查询结果的内存中的一个区域,游标在运行DML语句时打开,完成后关闭。隐式游标只使用SQL%FOUND,SQL%NOTFOUND,SQL%ROWCOUNT三个属性.SQL%FOUND,SQL%NOTFOUND是布尔值,SQL%ROWCOUNT是整数值。 

SQL%FOUND和SQL%NOTFOUND 
在执行任何DML语句前SQL%FOUND和SQL%NOTFOUND的值都是NULL,在执行DML语句后,SQL%FOUND的属性值将是: 

. TRUE :INSERT 
. TRUE ELETE和UPDATE,至少有一行被DELETE或UPDATE. 
. TRUE :SELECT INTO至少返回一行 
当SQL%FOUND为TRUE时,SQL%NOTFOUND为FALSE。 

SQL%ROWCOUNT 
在执行任何DML语句之前,SQL%ROWCOUNT的值都是NULL,对于SELECT INTO语句,如果执行成功,SQL%ROWCOUNT的值为1,如果没有成功,SQL%ROWCOUNT的值为0,同时产生一个异常NO_DATA_FOUND. 

SQL%ISOPEN 
SQL%ISOPEN是一个布尔值,如果游标打开,则为TRUE, 如果游标关闭,则为FALSE.对于隐式游标而言SQL%ISOPEN总是FALSE,这是因为隐式游标在DML语句执行时打开,结束时就立即关闭。 

事务控制语句 
事务是一个工作的逻辑单元可以包括一个或多个DML语句,事物控制帮助用户保证数据的一致性。如果事务控制逻辑单元中的任何一个DML语句失败,那么整个事务都将回滚,在PL/SQL中用户可以明确地使用COMMIT、ROLLBACK、SAVEPOINT以及SET TRANSACTION语句。 
COMMIT语句终止事务,永久保存数据库的变化,同时释放所有LOCK,ROLLBACK终止现行事务释放所有LOCK,但不保存数据库的任何变化,SAVEPOINT用于设置中间点,当事务调用过多的数据库操作时,中间点是非常有用的,SET TRANSACTION用于设置事务属性,比如read-write和隔离级等。 

显式游标 
当查询返回结果超过一行时,就需要一个显式游标,此时用户不能使用select into语句。PL/SQL管理隐式游标,当查询开始时隐式游标打开,查询结束时隐式游标自动关闭。显式游标在PL/SQL块的声明部分声明,在执行部分或异常处理部分打开,取数据,关闭。 

使用游标 
这里要做一个声明,我们所说的游标通常是指显式游标,因此从现在起没有特别指明的情况,我们所说的游标都是指显式游标。要在程序中使用游标,必须首先声明游标。 

声明游标 
语法: 
CURSOR cursor_name IS select_statement; 

在PL/SQL中游标名是一个未声明变量,不能给游标名赋值或用于表达式中。 

例: 
DELCARE 
CURSOR C_EMP IS SELECT empno,ename,salary 
FROM emp 
WHERE salary>2000 
ORDER BY ename; 
........ 
BEGIN 
在游标定义中SELECT语句中不一定非要表可以是视图,也可以从多个表或视图中选择的列,甚至可以使用*来选择所有的列 。 

打开游标 
使用游标中的值之前应该首先打开游标,打开游标初始化查询处理。打开游标的语法是: 
OPEN cursor_name 
cursor_name是在声明部分定义的游标名。 

例: 
OPEN C_EMP; 

关闭游标 
语法: 
CLOSE cursor_name 

例: 
CLOSE C_EMP; 

从游标提取数据 
从游标得到一行数据使用FETCH命令。每一次提取数据后,游标都指向结果集的下一行。语法如下: 
FETCH cursor_name INTO variable[,variable,...] 
对于SELECT定义的游标的每一列,FETCH变量列表都应该有一个变量与之相对应,变量的类型也要相同。 

例: 
SET SERVERIUTPUT ON 
DECLARE 
v_ename EMP.ENAME%TYPE; 
v_salary EMP.SALARY%TYPE; 
CURSOR c_emp IS SELECT ename,salary FROM emp; 
BEGIN 
OPEN c_emp; 
FETCH c_emp INTO v_ename,v_salary; 
DBMS_OUTPUT.PUT_LINE('Salary of Employee'|| v_ename ||'is'|| v_salary); 
FETCH c_emp INTO v_ename,v_salary; 
DBMS_OUTPUT.PUT_LINE('Salary of Employee'|| v_ename ||'is'|| v_salary); 
FETCH c_emp INTO v_ename,v_salary; 
DBMS_OUTPUT.PUT_LINE('Salary of Employee'|| v_ename ||'is'|| v_salary); 
CLOSE c_emp; 
END 

这段代码无疑是非常麻烦的,如果有多行返回结果,可以使用循环并用游标属性为结束循环的条件,以这种方式提取数据,程序的可读性和简洁性都大为提高,下面我们使用循环重新写上面的程序: 
SET SERVERIUTPUT ON 
DECLARE 
v_ename EMP.ENAME%TYPE; 
v_salary EMP.SALARY%TYPE; 
CURSOR c_emp IS SELECT ename,salary FROM emp; 
BEGIN 
OPEN c_emp; 
LOOP 
FETCH c_emp INTO v_ename,v_salary; 
EXIT WHEN c_emp%NOTFOUND; 
DBMS_OUTPUT.PUT_LINE('Salary of Employee'|| v_ename ||'is'|| v_salary); 
END 

记录变量 
定义一个记录变量使用TYPE命令和%ROWTYPE,关于%ROWsTYPE的更多信息请参阅相关资料。 
记录变量用于从游标中提取数据行,当游标选择很多列的时候,那么使用记录比为每列声明一个变量要方便得多。 
当在表上使用%ROWTYPE并将从游标中取出的值放入记录中时,如果要选择表中所有列,那么在SELECT子句中使用*比将所有列名列出来要安全得多。 

例: 
SET SERVERIUTPUT ON 
DECLARE 
R_emp EMP%ROWTYPE; 
CURSOR c_emp IS SELECT * FROM emp; 
BEGIN 
OPEN c_emp; 
LOOP 
FETCH c_emp INTO r_emp; 
EXIT WHEN c_emp%NOTFOUND; 
DBMS_OUT.PUT.PUT_LINE('Salary of Employee'||r_emp.ename||'is'|| r_emp.salary); 
END LOOP; 
CLOSE c_emp; 
END; 

%ROWTYPE也可以用游标名来定义,这样的话就必须要首先声明游标: 

SET SERVERIUTPUT ON 
DECLARE 
CURSOR c_emp IS SELECT ename,salary FROM emp; 
R_emp c_emp%ROWTYPE; 
BEGIN 
OPEN c_emp; 
LOOP 
FETCH c_emp INTO r_emp; 
EXIT WHEN c_emp%NOTFOUND; 
DBMS_OUT.PUT.PUT_LINE('Salary of Employee'||r_emp.ename||'is'|| r_emp.salary); 
END LOOP; 
CLOSE c_emp; 
END; 

带参数的游标 
与存储过程和函数相似,可以将参数传递给游标并在查询中使用。这对于处理在某种条件下打开游标的情况非常有用。它的语法如下: 

CURSOR cursor_name[(parameter[,parameter],...)] IS select_statement; 

定义参数的语法如下: 
Parameter_name [IN] data_type[{:=|DEFAULT} value] 

  与存储过程不同的是,游标只能接受传递的值,而不能返回值。参数只定义数据类型,没有大小。 
另外可以给参数设定一个缺省值,当没有参数值传递给游标时,就使用缺省值。游标中定义的参数只是一个占位符,在别处引用该参数不一定可靠。 

在打开游标时给参数赋值,语法如下: 

OPEN cursor_name[value[,value]....]; 
参数值可以是文字或变量。 

例: 
DECALRE 
CURSOR c_dept IS SELECT * FROM dept ORDER BY deptno; 
CURSOR c_emp (p_dept VARACHAR2) IS 
SELECT ename,salary 
FROM emp 
WHERE deptno=p_dept 
ORDER BY ename 
r_dept DEPT%ROWTYPE; 
v_ename EMP.ENAME%TYPE; 
v_salary EMP.SALARY%TYPE; 
v_tot_salary EMP.SALARY%TYPE; 
BEGIN 
OPEN c_dept; 
LOOP 
FETCH c_dept INTO r_dept; 
EXIT WHEN c_dept%NOTFOUND; 
DBMS_OUTPUT.PUT_LINE('Department:'|| r_dept.deptno||'-'||r_dept.dname); 
v_tot_salary:=0; 
OPEN c_emp(r_dept.deptno); 
LOOP 
FETCH c_emp INTO v_ename,v_salary; 
EXIT WHEN c_emp%NOTFOUND; 
DBMS_OUTPUT.PUT_LINE('Name:'|| v_ename||' salary:'||v_salary); 
v_tot_salary:=v_tot_salary v_salary; 
END LOOP; 
CLOSE c_emp; 
DBMS_OUTPUT.PUT_LINE('Toltal Salary for dept:'|| v_tot_salary); 
END LOOP; 
CLOSE c_dept; 
END; 

游标FOR循环 
在大多数时候我们在设计程序的时候都遵循下面的步骤: 
1、打开游标 
2、开始循环 
3、从游标中取值 
4、检查那一行被返回 
5、处理 
6、关闭循环 
7、关闭游标 
可以简单的把这一类代码称为游标用于循环。但还有一种循环与这种类型不相同,这就是FOR循环,用于FOR循环的游标按照正常的声明方式声明,它的优点在于不需要显式的打开、关闭、取数据,测试数据的存在、定义存放数据的变量等等。游标FOR循环的语法如下: 

FOR record_name IN 
(corsor_name[(parameter[,parameter]...)] 
| (query_difinition) 
LOOP 
statements 
END LOOP; 

下面我们用for循环重写上面的例子: 
DECALRE 
CURSOR c_dept IS SELECT deptno,dname FROM dept ORDER BY deptno; 
CURSOR c_emp (p_dept VARACHAR2) IS 
SELECT ename,salary 
FROM emp 
WHERE deptno=p_dept 
ORDER BY ename 
v_tot_salary EMP.SALARY%TYPE; 
BEGIN 
FOR r_dept IN c_dept LOOP 
DBMS_OUTPUT.PUT_LINE('Department:'|| r_dept.deptno||'-'||r_dept.dname); 
v_tot_salary:=0; 
FOR r_emp IN c_emp(r_dept.deptno) LOOP 
DBMS_OUTPUT.PUT_LINE('Name:' || v_ename || 'salary:' || v_salary); 
v_tot_salary:=v_tot_salary v_salary; 
END LOOP; 
DBMS_OUTPUT.PUT_LINE('Toltal Salary for dept:'|| v_tot_salary); 
END LOOP; 
END; 

在游标FOR循环中使用查询 
在游标FOR循环中可以定义查询,由于没有显式声明所以游标没有名字,记录名通过游标查询来定义。 
DECALRE 
v_tot_salary EMP.SALARY%TYPE; 
BEGIN 
FOR r_dept IN (SELECT deptno,dname FROM dept ORDER BY deptno) LOOP 
DBMS_OUTPUT.PUT_LINE('Department:'|| r_dept.deptno||'-'||r_dept.dname); 
v_tot_salary:=0; 
FOR r_emp IN (SELECT ename,salary 
   FROM emp 
   WHERE deptno=p_dept 
   ORDER BY ename) LOOP 
DBMS_OUTPUT.PUT_LINE('Name:'|| v_ename||' salary:'||v_salary); 
v_tot_salary:=v_tot_salary v_salary; 
END LOOP; 
DBMS_OUTPUT.PUT_LINE('Toltal Salary for dept:'|| v_tot_salary); 
END LOOP; 
END; 

游标中的子查询 
语法如下: 

CURSOR C1 IS SELECT * FROM emp 
WHERE deptno NOT IN (SELECT deptno 
FROM dept 
WHERE dname!='ACCOUNTING'); 
可以看出与SQL中的子查询没有什么区别。 

游标中的更新和删除 
在PL/SQL中依然可以使用UPDATE和DELETE语句更新或删除数据行。显式游标只有在需要获得多行数据的情况下使用。PL/SQL提供了仅仅使用游标就可以执行删除或更新记录的方法。 
UPDATE或DELETE语句中的WHERE CURRENT OF子串专门处理要执行UPDATE或DELETE操作的表中取出的最近的数据。要使用这个方法,在声明游标时必须使用FOR UPDATE子串,当对话使用FOR UPDATE子串打开一个游标时,所有返回集中的数据行都将处于行级(ROW-LEVEL)独占式锁定,其他对象只能查询这些数据行,不能进行UPDATE、DELETE或SELECT...FOR UPDATE操作。 

语法: 
FOR UPDATE [OF [schema.]table.column[,[schema.]table.column].. 
[nowait] 

在多表查询中,使用OF子句来锁定特定的表,如果忽略了OF子句,那么所有表中选择的数据行都将被锁定。如果这些数据行已经被其他会话锁定,那么正常情况下ORACLE将等待,直到数据行解锁。 

在UPDATE和DELETE中使用WHERE CURRENT OF子串的语法如下: 

WHERE{CURRENT OF cursor_name|search_condition} 

例: 
DELCARE 
CURSOR c1 IS SELECT empno,salary 
FROM emp 
WHERE comm IS NULL 
FOR UPDATE OF comm; 
v_comm NUMBER(10,2); 
BEGIN 
FOR r1 IN c1 LOOP 
IF r1.salary<500 THEN 
v_comm:=r1.salary*0.25; 
ELSEIF r1.salary<1000 THEN 
v_comm:=r1.salary*0.20; 
ELSEIF r1.salary<3000 THEN 
v_comm:=r1.salary*0.15; 
ELSE 
v_comm:=r1.salary*0.12; 
END IF; 
UPDATE emp; 
SET comm=v_comm 
WHERE CURRENT OF c1l; 
END LOOP; 
END

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
Oracle数据库游标使用大全--heroym
【转】数据库游标的概念和作用
Oracle--plsql游标创建和使用
Oracle PL/SQL随堂笔记总结
Oracle 游标
ORACLE索引与高性能SQL介绍
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服