Oracle笔记

视图的创建

一.what(什么是视图?)

1.视图是一种数据库对象,是从一个或者多个数据表或视图中导出的虚表,视图所对应的数据并不真正地存储在视图中,而是存储在所引用的数据表中,视图的结构和数据是对数据表进行查询的结果。
2.根据创建视图时给定的条件,视图可以是一个数据表的一部分,也可以是多个基表的联合,它存储了要执行检索的查询语句的定义,以便在引用该视图时使用。

二.why(为什么要用视图?视图的优点)

1.简化数据操作:视图可以简化用户处理数据的方式。
2.着重于特定数据:不必要的数据或敏感数据可以不出现在视图中。
3.视图提供了一个简单而有效的安全机制,可以定制不同用户对数据的访问权限。
4.提供向后兼容性:视图使用户能够在表的架构更改时为表创建向后兼容接口。
5.自定义数据:视图允许用户以不同方式查看数据。
6.导出和导入数据:可使用视图将数据导出到其他应用程序。
 
三.how(视图的创建语法、删除、demo)

CREATE [OR REPLACE] [FORCE|NOFORCE] VIEW view_name [(alias[, alias]...)] AS subquery [WITH CHECK OPTION [CONSTRAINT constraint]] [WITH READ ONLY] 
OR REPLACE    :若所创建的试图已经存在,ORACLE自动重建该视图;
FORCE  :不管基表是否存在ORACLE都会自动创建该视图;
NOFORCE   :只有基表都存在ORACLE才会创建该视图:
alias :为视图产生的列定义的别名;
subquery     :一条完整的SELECT语句,可以在该语句中定义别名;
WITH CHECK  OPTION :插入或修改的数据行必须满足视图定义的约束; WITH READ ONLY :该视图上不能进行任何DML操作。

CREATE  OR  REPLACE  VIEW  dept_sum_vw 
(name,minsal,maxsal,avgsal) 
AS SELECT d.dname,min(e.sal),max(e.sal),avg(e.sal) FROM emp e,dept d WHERE e.deptno=d.deptno GROUP BY d.dname; 
--给用户授权创建视图
-- grant create all view to zdgshr;      所有数据库都能创建视图的用户
grant create view to zdgshr; --创建简单视图 create view temp as select * from zd_member_basic_info; --测试 select * from temp where rownum=1; --创建简单视图:只读 create or replace view temp1 as select id,job_number,name,dept_id from zd_member_basic_info with read only; --测试 insert into temp1(id,job_number,name,dept_id) values(1,0,'张三',1300);


2、嵌套查询

概念:

所谓子查询,即一个select语句中嵌套了另外的一个或者多个select语句

需求:查找和Smith同部门的所有员工的idlast_name

目标: 员工id,last_name

from:  s_emp

条件: s_emp.dept_id = Smith所在部门的id

select id,last_name

from s_emp

where dept_id = ?

阶段目标: Smith所在部门的id

目标: dept_id

from : s_emp

条件: last_name = 'Smith';

select dept_id

from s_emp

where last_name = 'Smith';

组合:

select id,last_name

from s_emp

where dept_id = (

select dept_id

from s_emp

where last_name = 'Smith'

)

应用场景:

1.一条查询语句的查询条件依赖另外一条查询语句的查询结果。

2.一条查询语句的查询结果是作为另外一条查询语句的查询表(查询依据)

3.DML操作中使用子查询(后期介绍)

子查询的基本原则:

1.在查询中可以有单行子查询和多行子查询

2.子查询可以出现在操作符的左边或者右边

3.子查询在很多sql命令中都可以使用

4.嵌套查询先执行,然后将结果传递给主查询。

一、比较值不确定,需要另外一个select语句执行后才能得到,使用子查询

语法:

select ...

from ...

where col_name 比较操作符 (

select ...

from ...

where ...

group by ...

having...

)

group by ...

having...

order by ...

单值子查询:子查询的结果为1

需求:

1.查询和Simith职称相同的所有员工的last_name和职称

分析步骤:

1.确定最终查询结果(目标/主查询):查询员工的last_nametitle

  from : s_emp

  条件  title = Smith的职称

select last_name,title

from s_emp

where title = ?

2.确定条件(子查询)Smith的职称

from : s_emp

条件 last_name = 'Smith';

select title

from s_emp

where last_name = 'Smith';

3.组合

select last_name,title

from s_emp

where title = (select title

from s_emp

where last_name = 'Smith');

2.查看工资大于Chang员工工资的所有员工的id和名字。

最终目标:员工的id,last_name

froms_emp

条件: salary > Chang员工的工资

select id,last_name

from s_emp

where salary > ?

 

阶段目标:Chang员工的工资

from : s_emp

条件: last_name = 'Chang';

select salary

from s_emp

where last_name = 'Chang';

 

组合:

3.查看员工工资小于平均工资的所有员工的id和名字

 例如:查找和Smith同一个部门的员工的idlast_name

 多值子查询:子查询的结果为多个

需求:

1.查询所在区域为2号区域的所有部门的员工的idlast_name

 1.确定最终查询结果: 员工的id, last_name

   from : s_emp

   条件 s_emp.dept_id  in (?);

select id,last_name

from s_emp

where dept_id  in ?

 2.确定条件:所在区域为2号部门id

子查询:部门id

from : s_dept

条件: region_id = 2;

select id

from s_dept

where region_id = 2;

 3.组合:

select id,last_name

from s_emp

where dept_id  in (

select id

from s_dept

where region_id = 2

)

  子查询出现情况二:

查找的内容不确定,需要从构建出来一个查询的表

语法:

select ....

from (select .... from ....) b

where ......

 练习:查询各部门的idname 和部门员工的平均工资

1.查询目标:

需要部门的id,部门的name ------ 从 s_dept表中

部门员工的平均工资 avg(salary) --------- salary只有s_emp表中有

条件  部门idname和部门 员工,因此要求部门的id跟员工所在部门的id相等才连接

select id,name, 平均工资

from s_dept , ?

where s_dept.id = ?.dept_id;

 

2.查询条件

select(dept_id,avg(salary) sal)

from s_emp

group by dept_id;

 

3.组合:

select id,name,b.sal

from s_dept dept,(select dept_id,avg(salary) sal

from s_emp

group by dept_id

) b

where dept.id = b.dept_id; 概念:
所谓子查询,即一个select语句中嵌套了另外的一个或者多个select语句
需求:查找和Smith同部门的所有员工的id和last_name
目标: 员工id,last_name
from:  s_emp
条件: s_emp.dept_id = Smith所在部门的id?
select id,last_name
from s_emp
where dept_id = ?
阶段目标: Smith所在部门的id
目标: dept_id
from : s_emp
条件: last_name = 'Smith';
select dept_id
from s_emp
where last_name = 'Smith';
组合:
select id,last_name
from s_emp
where dept_id = (
select dept_id
from s_emp
where last_name = 'Smith'
)
应用场景:
1.一条查询语句的查询条件依赖另外一条查询语句的查询结果。
2.一条查询语句的查询结果是作为另外一条查询语句的查询表(查询依据)。
3.在DML操作中使用子查询(后期介绍)
子查询的基本原则:
1.在查询中可以有单行子查询和多行子查询
2.子查询可以出现在操作符的左边或者右边
3.子查询在很多sql命令中都可以使用
4.嵌套查询先执行,然后将结果传递给主查询。
一、比较值不确定,需要另外一个select语句执行后才能得到,使用子查询
语法:
select ...
from ...
where col_name 比较操作符 (
select ...
from ...
where ...
group by ...
having...
)
group by ...
having...
order by ...
单值子查询:子查询的结果为1个
需求:
1.查询和Simith职称相同的所有员工的last_name和职称
分析步骤:
1.确定最终查询结果(目标/主查询):查询员工的last_name和title
  from : s_emp
  条件 : title = Smith的职称
select last_name,title
from s_emp
where title = ?
2.确定条件(子查询):Smith的职称
from : s_emp
条件 :last_name = 'Smith';
select title
from s_emp
where last_name = 'Smith';
3.组合
select last_name,title
from s_emp
where title = (select title
from s_emp
where last_name = 'Smith');
2.查看工资大于Chang员工工资的所有员工的id和名字。
最终目标:员工的id,last_name
from:s_emp
条件: salary > Chang员工的工资
select id,last_name
from s_emp
where salary > ?
阶段目标:Chang员工的工资
from : s_emp
条件: last_name = 'Chang';
select salary
from s_emp
where last_name = 'Chang';
组合:
3.查看员工工资小于平均工资的所有员工的id和名字
例如:查找和Smith同一个部门的员工的id和last_name
多值子查询:子查询的结果为多个
需求:

1.查询所在区域为2号区域的所有部门的员工的id和last_name
 1.确定最终查询结果: 员工的id, last_name

   from : s_emp

 条件 :s_emp.dept_id  in (?);

select id,last_name
from s_emp
where dept_id  in ?
 2.确定条件:所在区域为2号部门id
子查询:部门id
from : s_dept
条件: region_id = 2;
select id
from s_dept
where region_id = 2;
 3.组合:
select id,last_name
from s_emp
where dept_id  in (
select id
from s_dept
where region_id = 2
)
子查询出现情况二:
查找的内容不确定,需要从构建出来一个查询的表
语法:
select ....
from (select .... from ....) b
where ......
练习:查询各部门的id,name 和部门员工的平均工资
1.查询目标:
需要部门的id,部门的name ------ 从 s_dept表中
部门员工的平均工资 avg(salary) --------- salary只有s_emp表中有
条件 : 部门id,name和部门 员工,因此要求部门的id跟员工所在部门的id相等才连接
select id,name, 平均工资
from s_dept , ?
where s_dept.id = ?.dept_id;
2.查询条件
select(dept_id,avg(salary) sal)
from s_emp
group by dept_id;
3.组合:
select id,name,b.sal
from s_dept dept,(select dept_id,avg(salary) sal
from s_emp
group by dept_id
) b

where dept.id = b.dept_id; 

3、表的类别

1、临时表

Oracle临时表可以说是提高数据库处理性能的好方法,在没有必要存储时,只存储在Oracle临时表空间中。希望本文能对大家有所帮助。

  1 、前言

  目前所有使用 Oracle 作为数据库支撑平台的应用,大部分数据量比较庞大的系统,即表的数据量一般情况下都是在百万级以上的数据量。

  当然在 Oracle 中创建分区是一种不错的选择,但是当你发现你的应用有多张表关联的时候,并且这些表大部分都是比较庞大,而你关联的时候发现其中的某一张或者某几张表关联 之后得到的结果集非常小并且查询得到这个结果集的速度非常快,那么这个时候我考虑在 Oracle 中创建“临时表”。

  我对临时表的理解:在 Oracle 中创建一张表,这个表不用于其他的什么功能,主要用于自己的软件系统一些特有功能才用的,而当你用完之后表中的数据就没用了。 Oracle 的临时表创建之后基本不占用表空间,如果你没有指定临时表(包括临时表的索引)存放的表空的时候,你插入到临时表的数据是存放在 ORACLE 系统的临时表空间中( TEMP )。

  2 、临时表的创建

  创建Oracle 临时表,可以有两种类型的临时表:

  会话级的临时表

  事务级的临时表 。

  1) 会话级的临时表因为这这个临时表中的数据和你的当前会话有关系,当你当前SESSION 不退出的情况下,临时表中的数据就还存在,而当你退出当前SESSION 的时候,临时表中的数据就全部没有了,当然这个时候你如果以另外一个SESSION 登陆的时候是看不到另外一个SESSION 中插入到临时表中的数据的。即两个不同的SESSION 所插入的数据是互不相干的。当某一个SESSION 退出之后临时表中的数据就被截断(truncate table ,即数据清空)了。会话级的临时表创建方法:

  1. Create Global Temporary Table Table_Name  
  2. (Col1 Type1,Col2 Type2...) On Commit Preserve Rows ; 

  举例:

  1. create global temporary table Student  
  2. (Stu_id Number(5),  
  3. Class_id Number(5),  
  4. Stu_Name Varchar2(8),  
  5. Stu_Memo varchar2(200)) on Commit Preserve Rows ; 

  2) 事务级临时表是指该临时表与事务相关,当进行事务提交或者事务回滚的时候,临时表中的数据将自行被截断,其他的内容和会话级的临时表的一致(包括退出SESSION 的时候,事务级的临时表也会被自动截断)。事务级临时表的创建方法:

  1. Create Global Temporary Table Table_Name  
  2. (Col1 Type1,Col2 Type2...) On Commit Delete Rows ; 

  举例:

  1. create global temporary table Classes  
  2. (Class_id Number(5),  
  3. Class_Name Varchar2(8),  
  4. Class_Memo varchar2(200)) on Commit delete Rows ; 

  3) 两中类型临时表的区别

  会话级临时表采用 on commit preserve rows ;而事务级则采用 on commit delete rows ;用法上,会话级别只有当会话结束临时表中的数据才会被截断,而且事务级临时表则不管是 commit 、 rollback 或者是会话结束,临时表中的数据都将被截断

  4 )什么时候使用临时表

  1 )、当某一个 SQL 语句关联的表在 2 张及以上,并且和一些小表关联。可以采用将大表进行分拆并且得到比较小的结果集合存放在临时表中

  2 )、程序执行过程中可能需要存放一些临时的数据,这些数据在整个程序的会话过程中都需要用的等等。

  3 . 例子:

       临时表的定义对所有会话SESSION都是可见的,但是表中的数据只对当前的会话或者事务有效

    (1)

    CREATE GLOBAL TEMPORARY TABLE admin_work_area
    (startdate DATE,
    enddate DATE,
    class CHAR(20))
    ON COMMIT PRESERVE ROWS;

(2)

CREATE GLOBAL TEMPORARY TABLE admin_work_area
2  (startdate DATE,
3  enddate DATE,
4  class CHAR(20))
5  ON COMMIT DELETE ROWS;

 

  4 .临时表的不足之处

  1 )不支持 lob 对象,这也许是设计者基于运行效率的考虑,但实际应用中确实需要此功能时就无法使用临时表了。

  2 )不支持主外键关系

  所以,由于以上原因,我们可以自己创建临时表,以弥补 oracle 临时表的不足之处

  上面的都是本人经过测试的,但下面是在网上搜索到的方法,本人具体没有测试过,不过觉得可行性很强,有时间测试下

  创建方法:

  1 、以常规表的形式创建临时数据表的表结构,但要在每一个表的主键中加入一个 SessionID 列以区分不同的会话。(可以有 lob 列和主外键)

  2 、写一个用户注销触发器,在用户结束会话的时候删除本次会话所插入的所有记录 (SessionID 等于本次会话 ID 的记录 ) 。

  3 、程序写入数据时,要顺便将当前的会话 ID(SessionID) 写入表中。

  4 、程序读取数据时,只读取与当前会话 ID 相同的记录即可。

  功能增强的扩展设计:

  1 、可以在数据表上建立一个视图,视图对记录的筛选条件就是当前会话的SessionID 。

  2 、数据表中的SessionID 列可以通过Trigger 实现,以实现对应用层的透明性。

  3 、高级用户可以访问全局数据,以实现更加复杂的功能。

  扩展临时表的优点:

  1 、实现了与Oracle 的基于会话的临时表相同的功能。

  2 、支持SDO_GEOMETRY 等lob 数据类型。

  3 、支持表间的主外键连接,且主外键连接也是基于会话的。

  4 、高级用户可以访问全局数据,以实现更加复杂的功能

 

删除临时表:

对于session的 必须先truncate ,才能drop

对于事物的,必须先commit ,才能drop

2、基础表

3、Oracle数据类型

一、数据类型
1.char(n) n=1 to 2000字节 定长字符串,n字节长,如果不指定长度,缺省为1个字节长(一个汉字为2字节)
2.varchar2(n) n=1 to 4000字节 可变长的字符串,具体定义时指明最大长度n,这种数据类型可以放数字、字母以及ASCII码字符集(或者EBCDIC等数据库系统接受的字符集标准)中的所有符号。
如果数据长度没有达到最大值n,Oracle 8i会根据数据大小自动调节字段长度,
如果你的数据前后有空格,Oracle 8i会自动将其删去。VARCHAR2是最常用的数据类型。
可做索引的最大长度3209。
3.number(m,n) m=1 to 38n=-84 to 127 可变长的数值列,允许0、正值及负值,m是所有有效数字的位数,n是小数点以后的位数。
如:number(5,2),则这个字段的最大值是99,999,如果数值超出了位数限制就会被截取多余的位数。
如:number(5,2),但在一行数据中的这个字段输入575.316,则真正保存到字段中的数值是575.32。
如:number(3,0),输入575.316,真正保存的数据是575。 
4.date 无 从公元前4712年1月1日到公元4712年12月31日的所有合法日期,
Oracle 8i其实在内部是按7个字节来保存日期数据,在定义中还包括小时、分、秒。
缺省格式为DD-MON-YY,如07-11月-00 表示2000年11月7日。 
5.long 无 可变长字符列,最大长度限制是2GB,用于不需要作字符串搜索的长串数据,如果要进行字符搜索就要用varchar2类型。
long是一种较老的数据类型,将来会逐渐被BLOB、CLOB、NCLOB等大的对象数据类型所取代。 
6.raw(n) n=1 to 2000 可变长二进制数据,在具体定义字段的时候必须指明最大长度n,Oracle 8i用这种格式来保存较小的图形文件或带格式的文本文件,如Miceosoft Word文档。
raw是一种较老的数据类型,将来会逐渐被BLOB、CLOB、NCLOB等大的对象数据类型所取代。 
long raw 无 可变长二进制数据,最大长度是2GB。Oracle 8i用这种格式来保存较大的图形文件或带格式的文本文件,如Miceosoft Word文档,以及音频、视频等非文本文件。
在同一张表中不能同时有long类型和long raw类型,long raw也是一种较老的数据类型,将来会逐渐被BLOB、CLOB、NCLOB等大的对象数据类型所取代。 
blob
clob
nclob 无 三种大型对象(LOB),用来保存较大的图形文件或带格式的文本文件,如Miceosoft Word文档,以及音频、视频等非文本文件,最大长度是4GB。
LOB有几种类型,取决于你使用的字节的类型,Oracle 8i实实在在地将这些数据存储在数据库内部保存。
可以执行读取、存储、写入等特殊操作。 
bfile 无 在数据库外部保存的大型二进制对象文件,最大长度是4GB。
这种外部的LOB类型,通过数据库记录变化情况,但是数据的具体保存是在数据库外部进行的。
Oracle 8i可以读取、查询BFILE,但是不能写入。
大小由操作系统决定。 
数据类型是列或存储过程中的一个属性。
    Oracle支持的数据类型可以分为三个基本种类:字符数据类型、数字数据类型以及表示其它数据的数据类型。
   

二、字符数据类型
      1.CHAR             char数据类型存储固定长度的字符值。一个CHAR数据类型可以包括1到2000个字符。如果对CHAR没有明确地说明长度,它的默认长度则设置为1。 如果对某个CHAR类型变量赋值,其长度小于规定的长度,那么Oracle自动用空格填充。
     2。 VARCHAR2 存储可变长度的字符串。虽然也必须指定一个VARCHAR2数据变量的长度,但是这个长度是指对该变量赋值的最大长度而非实际赋值长度。不需用空格填充。 最多可设置为4000个字符。因为VARCHAR2数据类型只存储为该列所赋的字符(不加空格),所以VARCHAR2需要的存储空间比CHAR数据类型 要小。
    Oracle推荐使用VARCHAR2
      3.NCHAR和NVARCHAR2 NCHAR和NVARCHAR2数据类型分别存储固定长度与可变长度的字符串,但是它们使用的是和数据库其他类型不同的字符集。在创建数据库时,需要指定 所使用的字符集,以便对数据中数据进行编码。还可以指定一个辅助的字符集[即本地语言集]。NCHAR和NVARCHAR2类型的列使用辅助字符集。 NCHAR和NVARCHAR2类型的列使用辅助字符集。
      在Oracle 9i中,可以以字符而不是字节为单位表示NCHAR和NVARCHAR2列的长度。
      4.LONG long数据类型可以存放2GB的字符数据,它是从早期版本中继承下来的。现在如果存储大容量的数据,Oracle推荐使用CLOB和NCLOB数据类型。在表和SQL语句中使用LONG类型有许多限制。
      CLOB和NCLOB    CLOB和NCLOB数据类型可以存储多达4GB的字符数据。NCLOB数据类型可存储NLS数据。
     

三、 数字数据类型
      Oracle使用标准、可变长度的内部格式来存储数字。这个内部格式精度可以高达38位。
      NUMBER数据类型可以有两个限定符,如:column NUMBER(precision,scale)。precision表示数字中的有效位。如果没有指定precision的话,Oracle将使用38 作为精度。scale表示小数点右边的位数,scale默认设置为0。如果把scale设成负数,Oracle将把该数字取舍到小数点左边的指定位数。
      日期数据类型
       Oracle标准日期格式为:DD-MON-YY HH:MI:SS
       通过修改实例的参数NLS_DATE_FORMAT,可以改变实例中插入日期的格式。在一个会话期间,可以通过Alter session SQL命令来修改日期,或者通过使用SQL语句的TO_DATE表达式中的参数来更新一个特定值。
       其它的数据类型
       RAW和LONG RAW    RAW和LONG RAW数据类型主要用于对数据库进行解释。指定这两种类型时,Oracle以位的形式来存储数据。RAW数据类型一般用于存储有特定格式的对象,如位图。 RAW数据类型可占用2KB的空间,而LONG RAW数据类型则可以占用2GB大小。
       ROWID ROWID是一种特殊的列类型,称之为伪列(pseudocolumn)。ROWID伪列在SQL SELECT语句中可以像普通列那样被访问。Oracle数据库中每行都有一个伪列。ROWID表示行的地址,ROWID伪列用ROWID数据类型定义。
       ROWID与磁盘驱动的特定位置有关,因此,ROWID是获得行的最快方法。但是,行的ROWID会随着卸载和重载数据库而发生变化,因此建议不要在事务 中使用ROWID伪列的值。例如,一旦当前应用已经使用完记录,就没有理由保存行的ROWID。不能通过任何SQL语句来设置标准的ROWID伪列的值。
      列或变量可以定义成ROWID数据类型,但是Oracle不能保证该列或变量的值是一个有效的ROWID。
    LOB(大型对象)数据类型,可以保存4GB的信息。LOB有以下3中类型:
      ,只能存储字符数据
    ,保存本地语言字符集数据
        ,以二进制信息保存数据
      可以指定将一个LOB数据保存在Oracle数据库内,还是指向一个包含次数据的外部文件。
      LOB可以参与事务。管理LOB中的数据必须通过DBMS_LOB PL/SQL内置软件包或者OGI接口。
      为了便于将LONG数据类型转换成LOB,Oracle 9i包含许多同时支持LOB和LONG的函数,喊包括一个ALTER TABLE语句的新选择,它允许将LONG数据类型自动转换成LOB。
    BFILE
      BFILE数据类型用做指向存储在Oracle数据库以外的文件的指针。
      XML Type
      作为对XML支持的一部分,Oracle 9i包含了一个新的数据类型XML Type。定义为XMLType的列将存储一个字符LOB列中的XML文档。有许多内置的功能可以使你从文档中抽取单个节点,还可以在XML Type文档中对任何节点创建索引。
      用户自定义数据
      从Oracle 8以后,用户可以定义自己的复杂数据类型,它们由Oracle基本数据类型组合而成。
      AnyType、AnyData和AnyDataSet
       Oracle包括3个新的数据类型,用于定义在现有数据类型之外的数据结构。其中每种数据类型必须用程序单元来定义,以便让Oracle9i知道如何处理这些类型的特定实现。
    类型转换
    Oracle会自动将某些数据类型转换成其他的数据类型,转换取决于包括该值的SQL语句。
    数据转换还可以通过Oracle的类型转换函数显示地进行。
    连接与比较
    在大多数平台上Oracle SQL中的连接操作符用两条竖线(||)表示。连接是将两个字符值连接。Oracle的自动类型转换功能使得两个数字值也可以进行连接。
    NULL
    NULL值是关系数据库的重要特征之一。实际上,NULL不代表任何值,它表示没有值。如果要创建表的一个列,而这个列必须有值,那么应将它指定为NOT NULL,这表示该列不能包含NULL值。
    任何数据类型都可以赋予NULL值。NULL值引入了SQL运算的三态逻辑。如果比较的一方是NULL值,那么会出现3种状态:TURE、FALSE以及两者都不是。
    因为NULL值不等于0或其他任何值,所以测试某个数据是否为NULL值只能通过关系运算符IS NULL来进行。
    NULL值特别适合以下情况:当一个列还未赋值时。如果选择不使用NULL值,那么必须对行的所有列都要赋值。这实际上也取消了某列不需要值的可能性,同时对它赋的值也很容易产生误解。这种情况则可能误导终端用户,并且导致累计操作的错误结果。
number(p,s)
p:1~38
s:-84~127
p>0,对s分2种情况:1. s>0
精确到小数点右边s位,并四舍五入。然后检验有效数位是否<=p;如果s>p,小数点右边至少有s-p个0填充。
2. s<0
精确到小数点左边s位,并四舍五入。然后检验有效数位是否<=p+|s|
123.2564 NUMBER 123.2564
1234.9876 NUMBER(6,2) 1234.99
12345.12345 NUMBER(6,2) Error
1234.9876 NUMBER(6) 1235
12345.345 NUMBER(5,-2) 12300
1234567 NUMBER(5,-2) 1234600
12345678 NUMBER(5,-2) Error
123456789 NUMBER(5,-4) 123460000
1234567890 NUMBER(5,-4) Error
12345.58 NUMBER(*, 1) 12345.6
0.1 NUMBER(4,5) Error
0.01234567 NUMBER(4,5) 0.01235
0.09999 NUMBER(4,5) 0.09999

oracle中to-char函数方法

知识点1:

在使用Oracle的to_date函数来做日期转换时,很多Java程序员也许会直接的采用“yyyy-MM-dd   HH:mm:ss”的格式

作为格式进行转换,但是在Oracle中会引起错误:“ORA   01810  格式代码出现两次”。

如:select   to_date( '2005-01-01   13:14:20 ', 'yyyy-MM-dd   HH24:mm:ss ')   from   dual; 

原因是:SQL中不区分大小写,MM和mm被认为是相同的格式代码,所以Oracle的SQL采用了mi代替分钟。 

select   to_date( '2005-01-01   13:14:20 ', 'yyyy-MM-dd   HH24:mi:ss ')   from   dual;

知识点2:假设当前时间为:2013-11-25 18:45:32

select   to_char(sysdate, 'yyyy-MM-dd   HH24:mi:ss ')   from   dual;     //mi是分钟             2013-11-25 18:45:32

select   to_char(sysdate, 'yyyy-MM-dd   HH24:mm:ss ')   from   dual;   //mm会显示月份   2013-11-25 18:11:32

知识点3:

1、转换函数

      与date操作关系最大的就是两个转换函数:to_date(),to_char()
      to_date() 作用将字符类型按一定格式转化为日期类型:
      具体用法:to_date(''2004-11-27'',''yyyy-mm-dd''),前者为字符串,后者为转换日期格式,注意,前后两者要以一对应。
      如;to_date(''2004-11-27 13:34:43'', ''yyyy-mm-dd hh24:mi:ss'') 将得到具体的时间

      多种日期格式:

      YYYY:四位表示的年份 
      YYY,YY,Y:年份的最后三位、两位或一位,缺省为当前世纪 
      MM:01~12的月份编号 
      MONTH:九个字符表示的月份,右边用空格填补 
      MON:三位字符的月份缩写 
      WW:一年中的星期 
      D:星期中的第几天 
      DD:月份中的第几天 
      DDD:年所中的第几天 
      DAY:九个字符表示的天的全称,右边用空格补齐 
      HH,HH12:一天中的第几个小时,12进制表示法 
      HH24:一天中的第几个小时,取值为00~23 
      MI:一小时中的分钟 
      SS:一分钟中的秒 
      SSSS:从午夜开始过去的秒数

      to_char():将日期转按一定格式换成字符类型
      SQL> select to_char(sysdate,''yyyy-mm-dd hh24:mi:ss'') time from dual;

      TIME
      -------------------
      2004-10-08 15:22:58

      即把当前时间按yyyy-mm-dd hh24:mi:ss格式转换成字符类型

      在oracle中处理日期大全

        TO_DATE格式  
      Day:  
      dd number 12  
      dy abbreviated fri  
      day spelled out friday  
      ddspth spelled out, ordinal twelfth  
      Month:  
      mm number 03  
      mon abbreviated mar  
      month spelled out march  
      Year:  
      yy two digits 98  
      yyyy four digits 1998 

      24小时格式下时间范围为: 0:00:00 - 23:59:59....  
      12小时格式下时间范围为: 1:00:00 - 12:59:59 .... 

      [ZT]日期和??函???
      1.  
      日期和字符转换函数用法(to_date,to_char) 

      2.  
      select to_char( to_date(222,''J''),''Jsp'') from dual 

      显示Two Hundred Twenty-Two 

      3.  
      求某天是星期几  
      select to_char(to_date(''2002-08-26'',''yyyy-mm-dd''),''day'') from dual; 

      星期一  
      select 
      to_char(to_date(''2002-08-26'',''yyyy-mm-dd''),''day'',''NLS_DATE_LANGUAGE 
      = American'') from dual;  
      monday  
      设置日期语言  
      ALTER SESSION SET NLS_DATE_LANGUAGE=''AMERICAN'';  
      也可以这样  
      TO_DATE (''2002-08-26'', ''YYYY-mm-dd'', ''NLS_DATE_LANGUAGE = American'') 

      4.  
      两个日期间的天数  
      select floor(sysdate - to_date(''20020405'',''yyyymmdd'')) from dual; 

      5. 时间为null的用法  
      select id, active_date from table1  
      union    
      select 1, TO_DATE(null) from dual; 

      注意要用TO_DATE(null) 

      6.  
      a_date between to_date(''20011201'',''yyyymmdd'') and 
      to_date(''20011231'',''yyyymmdd'')  
      那么12月31号中午12点之后和12月1号的12点之前是不包含在这个范围之内的。  
      所以,当时间需要精确的时候,觉得to_char还是必要的  
      7. 日期格式冲突问题  
      输入的格式要看你安装的ORACLE字符集的类型, 比如: US7ASCII, date格式的类型就是: ''01-Jan-01''  
      alter system set NLS_DATE_LANGUAGE = American  
      alter session set NLS_DATE_LANGUAGE = American  
      或者在to_date中写  
      select 
      to_char(to_date(''2002-08-26'',''yyyy-mm-dd''),''day'',''NLS_DATE_LANGUAGE 
      = American'') from dual;  
      注意我这只是举了NLS_DATE_LANGUAGE,当然还有很多,  
      可查看  
      select * from nls_session_parameters  
      select * from V$NLS_PARAMETERS 

      8.  
      select count(*)  
      from ( select rownum-1 rnum  
      from all_objects  
      where rownum <= to_date(''2002-02-28'',''yyyy-mm-dd'') - to_date(''2002-  
      02-01'',''yyyy-mm-dd'')+1  
      )  
      where to_char( to_date(''2002-02-01'',''yyyy-mm-dd'')+rnum-1, ''D'' )  
      not  
      in ( ''1'', ''7'' ) 

      查找2002-02-28至2002-02-01间除星期一和七的天数  
      在前后分别调用DBMS_UTILITY.GET_TIME, 让后将结果相减(得到的是1/100秒, 而不是毫秒). 

      9.  
      select months_between(to_date(''01-31-1999'',''MM-DD-YYYY''),  
      to_date(''12-31-1998'',''MM-DD-YYYY'')) "MONTHS" FROM DUAL;  
      1 

      select months_between(to_date(''02-01-1999'',''MM-DD-YYYY''),  
      to_date(''12-31-1998'',''MM-DD-YYYY'')) "MONTHS" FROM DUAL; 

      1.03225806451613  
      10. Next_day的用法  
      Next_day(date, day) 

      Monday-Sunday, for format code DAY  
      Mon-Sun, for format code DY  
      1-7, for format code D 

      11  
      select to_char(sysdate,''hh:mi:ss'') TIME from all_objects  
      注意:第一条记录的TIME 与最后一行是一样的  
      可以建立一个函数来处理这个问题  
      create or replace function sys_date return date is  
      begin  
      return sysdate;  
      end; 

      select to_char(sys_date,''hh:mi:ss'') from all_objects;  
      12.  
      获得小时数 

      SELECT EXTRACT(HOUR FROM TIMESTAMP ''2001-02-16 2:38:40'') from offer  
      SQL> select sysdate ,to_char(sysdate,''hh'') from dual; 

      SYSDATE TO_CHAR(SYSDATE,''HH'')  
      -------------------- ---------------------  
      2003-10-13 19:35:21 07 

      SQL> select sysdate ,to_char(sysdate,''hh24'') from dual; 

      SYSDATE TO_CHAR(SYSDATE,''HH24'')  
      -------------------- -----------------------  
      2003-10-13 19:35:21 19 

      获取年月日与此类似  
      13.  
      年月日的处理  
      select older_date,  
      newer_date,  
      years,  
      months,  
      abs(  
      trunc(  
      newer_date-  
      add_months( older_date,years*12+months )  
      )  
      ) days  
      from ( select  
      trunc(months_between( newer_date, older_date )/12) YEARS,  
      mod(trunc(months_between( newer_date, older_date )),  
      12 ) MONTHS,  
      newer_date,  
      older_date  
      from ( select hiredate older_date,  
      add_months(hiredate,rownum)+rownum newer_date  
      from emp )  
      ) 

      14.  
      处理月份天数不定的办法  
      select to_char(add_months(last_day(sysdate) +1, -2), 
      ''yyyymmdd''),last_day(sysdate) from dual 

      16.  
      找出今年的天数  
      select add_months(trunc(sysdate,''year''), 12) - trunc(sysdate,''year'') 
      from dual 

      闰年的处理方法  
      to_char( last_day( to_date(''02'' || :year,''mmyyyy'') ), ''dd'' )  
      如果是28就不是闰年 

      17.  
      yyyy与rrrr的区别  
      ''YYYY99 TO_C  
      ------- ----  
      yyyy 99 0099  
      rrrr 99 1999  
      yyyy 01 0001  
      rrrr 01 2001 

      18.不同时区的处理  
      select to_char( NEW_TIME( sysdate, ''GMT'',''EST''), ''dd/mm/yyyy 
      hh:mi:ss'') ,sysdate  
      from dual; 

      19.  
      5秒钟一个间隔  
      Select TO_DATE(FLOOR(TO_CHAR(sysdate,''SSSSS'')/300) * 300,''SSSSS'') 
      ,TO_CHAR(sysdate,''SSSSS'')  
      from dual 

      2002-11-1 9:55:00 35786  
      SSSSS表示5位秒数 

      20.  
      一年的第几天  
      select TO_CHAR(SYSDATE,''DDD''),sysdate from dual  
      310 2002-11-6 10:03:51 

      21.计算小时,分,秒,毫秒  
      select  
      Days,  
      A,  
      TRUNC(A*24) Hours,  
      TRUNC(A*24*60 - 60*TRUNC(A*24)) Minutes,  
      TRUNC(A*24*60*60 - 60*TRUNC(A*24*60)) Seconds,  
      TRUNC(A*24*60*60*100 - 100*TRUNC(A*24*60*60)) mSeconds  
      from  
      (  
      select  
      trunc(sysdate) Days,  
      sysdate - trunc(sysdate) A  
      from dual  
      ) 

 

      select * from tabname  
      order by decode(mode,''FIFO'',1,-1)*to_char(rq,''yyyymmddhh24miss''); 

      //  
      floor((date2-date1) /365) 作为年  
      floor((date2-date1, 365) /30) 作为月  
      mod(mod(date2-date1, 365), 30)作为日.  
      23.next_day函数  
      next_day(sysdate,6)是从当前开始下一个星期五。后面的数字是从星期日开始算起。  
      1 2 3 4 5 6 7  
      日 一 二 三 四 五 六

      oracle中有很多关于日期的函数

      在oracle中有很多关于日期的函数,如: 
      1、add_months()用于从一个日期值增加或减少一些月份 
      date_value:=add_months(date_value,number_of_months) 
      例: 
      SQL> select add_months(sysdate,12) "Next Year" from dual;

      Next Year 
      ---------- 
      13-11月-04

      SQL> select add_months(sysdate,112) "Last Year" from dual;

      Last Year 
      ---------- 
      13-3月 -13

      SQL>

      2、current_date()返回当前会放时区中的当前日期 
      date_value:=current_date 
      SQL> column sessiontimezone for a15 
      SQL> select sessiontimezone,current_date from dual;

      SESSIONTIMEZONE CURRENT_DA 
      --------------- ---------- 
      +08:00 13-11月-03

      SQL> alter session set time_zone=''-11:00'' 
        2 /

      会话已更改。

      SQL> select sessiontimezone,current_timestamp from dual;

      SESSIONTIMEZONE CURRENT_TIMESTAMP 
      --------------- ------------------------------------ 
      -11:00 12-11月-03 04.59.13.668000 下午 -11: 
                      00

      SQL>

      3、current_timestamp()以timestamp with time zone数据类型返回当前会放时区中的当前日期 
      timestamp_with_time_zone_value:=current_timestamp([timestamp_precision]) 
      SQL> column sessiontimezone for a15 
      SQL> column current_timestamp format a36 
      SQL> select sessiontimezone,current_timestamp from dual;

      SESSIONTIMEZONE CURRENT_TIMESTAMP 
      --------------- ------------------------------------ 
      +08:00 13-11月-03 11.56.28.160000 上午 +08: 
                      00

      SQL> alter session set time_zone=''-11:00'' 
        2 /

      会话已更改。

      SQL> select sessiontimezone,current_timestamp from dual;

      SESSIONTIMEZONE CURRENT_TIMESTAMP 
      --------------- ------------------------------------ 
      -11:00 12-11月-03 04.58.00.243000 下午 -11: 
                      00

      SQL>

      4、dbtimezone()返回时区 
      varchar_value:=dbtimezone 
      SQL> select dbtimezone from dual;

      DBTIME 
      ------ 
      -07:00

      SQL>

      5、extract()找出日期或间隔值的字段值 
      date_value:=extract(date_field from [datetime_value|interval_value]) 
      SQL> select extract(month from sysdate) "This Month" from dual;

      This Month 
      ---------- 
              11

      SQL> select extract(year from add_months(sysdate,36)) "3 Years Out" from 
      dual;

      3 Years Out 
      ----------- 
             2006

      SQL>

      6、last_day()返回包含了日期参数的月份的最后一天的日期 
      date_value:=last_day(date_value) 
      SQL> select last_day(date''2000-02-01'') "Leap Yr?" from dual;

      Leap Yr? 
      ---------- 
      29-2月 -00

      SQL> select last_day(sysdate) "Last day of this month" from dual;

      Last day o 
      ---------- 
      30-11月-03

      SQL>

      7、localtimestamp()返回会话中的日期和时间 
      timestamp_value:=localtimestamp 
      SQL> column localtimestamp format a28 
      SQL> select localtimestamp from dual;

      LOCALTIMESTAMP 
      ---------------------------- 
      13-11月-03 12.09.15.433000 
      下午

      SQL> select localtimestamp,current_timestamp from dual;

      LOCALTIMESTAMP CURRENT_TIMESTAMP 
      ---------------------------- ------------------------------------ 
      13-11月-03 12.09.31.006000 13-11月-03 12.09.31.006000 下午 +08: 
      下午 00

      SQL> alter session set time_zone=''-11:00'';

      会话已更改。

      SQL> select localtimestamp,to_char(sysdate,''DD-MM-YYYY HH:MI:SS AM'') 
      "SYSDATE" from dual;

      LOCALTIMESTAMP SYSDATE 
      ---------------------------- ------------------------ 
      12-11月-03 05.11.31.259000 13-11-2003 12:11:31 下午 
      下午

      SQL>

      8、months_between()判断两个日期之间的月份数量 
      number_value:=months_between(date_value,date_value) 
      SQL> select months_between(sysdate,date''1971-05-18'') from dual;

      MONTHS_BETWEEN(SYSDATE,DATE''1971-05-18'') 
      ---------------------------------------- 
                                    389.855143

      SQL> select months_between(sysdate,date''2001-01-01'') from dual;

      MONTHS_BETWEEN(SYSDATE,DATE''2001-01-01'') 
      ---------------------------------------- 
                                    34.4035409

      SQL>

      9、next_day()给定一个日期值,返回由第二个参数指出的日子第一次出现在的日期值(应返回相应日子的名称字符串)

      ?周相?日期函?

      1.查询某周的第一天
      select trunc(decode(ww, 53, to_date(yy || ''3112'', ''yyyyddmm''), 
      to_date(yy || ''-'' || to_char(ww * 7), ''yyyy-ddd'')), ''d'') last_day
      from (select substr(''2004-32'', 1, 4) yy, to_number(substr(''2004-32'', 
      6)) ww
               from dual)

      select 
      trunc(to_date(substr(''2003-01'',1,5)||to_char((to_number(substr(''2003-01'',6)))*7),''yyyy-ddd''),''d'')-6 
      first_day from dual

      select min(v_date) from
        (select (to_date(''200201'',''yyyymm'') + rownum) v_date
        from all_tables
        where rownum < 370)
      where to_char(v_date,''yyyy-iw'') = ''2002-49''

      2.查询某周的最后一天
      select trunc(decode(ww, 53, to_date(yy || ''3112'', ''yyyyddmm''), 
      to_date(yy || ''-'' || to_char(ww * 7), ''yyyy-ddd'')), ''d'') - 6 
      first_day
        from (select substr(''2004-33'', 1, 4) yy, to_number(substr(''2004-33'', 
      6)) ww
                from dual)
                
      select 
      trunc(to_date(substr(''2003-01'',1,5)||to_char((to_number(substr(''2003-01'',6)))*7),''yyyy-ddd''),''d'') 
      last_day from dual

      select max(v_date) from
        (select (to_date(''200408'',''yyyymm'') + rownum) v_date
        from all_tables
        where rownum < 370)
      where to_char(v_date,''yyyy-iw'') = ''2004-33''

      3.查询某周的日期
      select min_date, to_char(min_date,''day'') day from
      (select to_date(substr(''2004-33'',1,4)||''001''+rownum-1,''yyyyddd'') 
      min_date 
              from all_tables
        where rownum <= 
      decode(mod(to_number(substr(''2004-33'',1,4)),4),0,366,365)  
        union  

        select to_date(substr(''2004-33'',1,4)-1||
               
      decode(mod(to_number(substr(''2004-33'',1,4))-1,4),0,359,358)+rownum,''yyyyddd'') 
      min_date 
              from all_tables          
                where rownum <= 7
        union  

        select to_date(substr(''2004-33'',1,4)+1||''001''+rownum-1,''yyyyddd'') 
      min_date 
              from all_tables          
                where rownum <= 7                       
      )
      where to_char(min_date,''yyyy-iw'') =''2004-33'' 
 
      SQL> set serverout on 
SQL> declare 
2 DateValue date; 
3 begin 
4 select sysdate into DateValue from dual; 
5 dbms_output.put_line('源时间:'||to_char(DateValue)); 
6 dbms_output.put_line('源时间减1天:'||to_char(DateValue-1)); 
7 dbms_output.put_line('源时间减1天1小时:'||to_char(DateValue-1-1/24)); 
8 dbms_output.put_line('源时间减1天1小时1分:'||to_char(DateValue-1-1/24-1/(24*60))); 
9 dbms_output.put_line('源时间减1天1小时1分1秒:'||to_char(DateValue-1-1/24-1/(24*60)-1/(24*60*6 
0))); 
10 end; 
11 / 
源时间:2003-12-29 11:53:41 
源时间减1天:2003-12-28 11:53:41 
源时间减1天1小时:2003-12-28 10:53:41 
源时间减1天1小时1分:2003-12-28 10:52:41 
源时间减1天1小时1分1秒:2003-12-28 10:52:40 

sql语言分为四大类

SQL语言共分为四大类:数据查询语言DQL,数据操纵语言DML,
数据定义语言DDL,数据控制语言DCL。

1 数据查询语言DQL
数据查询语言DQL基本结构是由SELECT子句,FROM子句,WHERE
子句组成的查询块:
SELECT <字段名表>
FROM <表或视图名>
WHERE <查询条件>

2 数据操纵语言
数据操纵语言DML主要有三种形式:
1) 插入:INSERT
2) 更新:UPDATE
3) 删除:DELETE

3 数据定义语言DDL
数据定义语言DDL用来创建数据库中的各种对象-----表、视图、
索引、同义词、聚簇等如:
CREATE TABLE/VIEW/INDEX/SYN/CLUSTER
| | | | |
表 视图 索引 同义词 簇

4 数据控制语言DCL
数据控制语言DCL用来授予或回收访问数据库的某种特权,并控制
数据库操纵事务发生的时间及效果,对数据库实行监视等。如:
1) GRANT:授权。
2) ROLLBACK [WORK] TO [SAVEPOINT]:回退到某一点。
回滚---ROLLBACK
回滚命令使数据库状态回到上次最后提交的状态。其格式为:
SQL>ROLLBACK;
3) COMMIT [WORK]:提交。
在数据库的插入、删除和修改操作时,只有当事务在提交到数据
库时才算完成。在事务提交前,只有操作数据库的这个人才能有权看
到所做的事情,别人只有在最后提交完成后才可以看到。
提交数据有三种类型:显式提交、隐式提交及自动提交。下面分
别说明这三种类型。
(1) 显式提交
用COMMIT命令直接完成的提交为显式提交。其格式为:
SQL>COMMIT;
(2) 隐式提交
用SQL命令间接完成的提交为隐式提交。这些命令是:
ALTER,AUDIT,COMMENT,CONNECT,CREATE,DISCONNECT,DROP,
EXIT,GRANT,NOAUDIT,QUIT,REVOKE,RENAME。
(3) 自动提交
若把AUTOCOMMIT设置为ON,则在插入、修改、删除语句执行后,
系统将自动进行提交,这就是自动提交。其格式为:
SQL>SET AUTOCOMMIT ON;

存储过程创建临时表,可清空

存储过程:

1、定义
所谓存储过程(Stored Procedure),就是一组用于完成特定数据库功能的SQL语句集,该SQL语句集经过
编译后存储在数据库系统中。在使用时候,用户通过指定已经定义的存储过程名字并给出相应的存储过程参数
来调用并执行它,从而完成一个或一系列的数据库操作。

2、存储过程的创建
Oracle存储过程包含三部分:过程声明,执行过程部分,存储过程异常。

(1)无参存储过程语法

create or replace procedure NoParPro  
 as  //声明  
 ;  
 begin // 执行  
 ;  
 exception//存储过程异常  
 ;  
 end;  

(2)带参存储过程实例

create or replace procedure queryempname(sfindno emp.empno%type)   
as  
   sName emp.ename%type;  
   sjob emp.job%type;  
begin  
       ....  
exception  
       ....  
end;

 

(3)带参数存储过程含赋值方式

create or replace procedure runbyparmeters    
    (isal in emp.sal%type,   
     sname out varchar,  
     sjob in out varchar)  
 as   
    icount number;  
 begin  
      select count(*) into icount from emp where sal>isal and job=sjob;  
      if icount=1 then  
        ....  
      else  
       ....  
     end if;  
exception  
     when too_many_rows then  
     DBMS_OUTPUT.PUT_LINE('返回值多于1行');  
     when others then  
     DBMS_OUTPUT.PUT_LINE('在RUNBYPARMETERS过程中出错!');  
end;  

其中参数IN表示输入参数,是参数的默认模式。
OUT表示返回值参数,类型可以使用任意Oracle中的合法类型。
OUT模式定义的参数只能在过程体内部赋值,表示该参数可以将某个值传递回调用他的过程
IN OUT表示该参数可以向该过程中传递值,也可以将某个值传出去。

(4)存储过程中游标定义使用

as //定义(游标一个可以遍历的结果集)   
CURSOR cur_1 IS   
  SELECT area_code,CMCODE,SUM(rmb_amt)/10000 rmb_amt_sn,  
         SUM(usd_amt)/10000 usd_amt_sn   
  FROM BGD_AREA_CM_M_BASE_T   
  WHERE ym >= vs_ym_sn_beg   
       AND ym <= vs_ym_sn_end   
  GROUP BY area_code,CMCODE;   
      
begin //执行(常用For语句遍历游标)       
FOR rec IN cur_1 LOOP   
  UPDATE xxxxxxxxxxx_T   
   SET rmb_amt_sn = rec.rmb_amt_sn,usd_amt_sn = rec.usd_amt_sn   
   WHERE area_code = rec.area_code   
   AND CMCODE = rec.CMCODE   
   AND ym = is_ym;   
END LOOP;  

 

(5)游标的定义

--显示cursor的处理
declare  
---声明cursor,创建和命名一个sql工作区
cursor cursor_name is  
    select real_name from account_hcz;
    v_realname varchar2(20);
begin 
    open cursor_name;---打开cursor,执行sql语句产生的结果集
    fetch cursor_name into v_realname;--提取cursor,提取结果集中的记录
    dbms_output.put_line(v_realname);
    close cursor_name;--关闭cursor
end;

3、在Oracle中对存储过程的调用 

(1)过程调用方式一

declare  
      realsal emp.sal%type;  
      realname varchar(40);  
      realjob varchar(40);  
begin   //过程调用开始  
      realsal:=1100;  
      realname:='';  
      realjob:='CLERK';  
      runbyparmeters(realsal,realname,realjob);--必须按顺序  
      DBMS_OUTPUT.PUT_LINE(REALNAME||'   '||REALJOB);  
END;  //过程调用结束 

(2)过程调用方式二

declare  
     realsal emp.sal%type;  
     realname varchar(40);  
     realjob varchar(40);  
begin    //过程调用开始  
     realsal:=1100;  
     realname:='';  
     realjob:='CLERK';  
     --指定值对应变量顺序可变  
     runbyparmeters(sname=>realname,isal=>realsal,sjob=>realjob);           
    DBMS_OUTPUT.PUT_LINE(REALNAME||'   '||REALJOB);  
END;  //过程调用结束  

(3)过程调用方式三(SQL命令行方式下)

1、SQL>exec  proc_emp('参数1','参数2');//无返回值过程调用  
2、SQL>var vsal number  
     SQL> exec proc_emp ('参数1',:vsal);// 有返回值过程调用  
      或者:call proc_emp ('参数1',:vsal);// 有返回值过程调用 

使用存储过程创建临时表:

1 CREATE OR REPLACE PROCEDURE PRODUCT_TEMP_UPDATE_PRC AS    第1行表示创建存储过程,名称PRODUCT_TEMP_UPDATE_PRC 
 2   PC_DELESTR   VARCHAR2(50); --删除临时表记录语句     第2~7行表示声明变量。
 3   PC_CREATESTR VARCHAR2(500); --创建临时表
 4   TABEXT       VARCHAR2(10); --用于判断临时表是否存在中间变量
 5 
 6   CUR_CTGY   PRODUCTINFO.CATEGORY%TYPE;
 7   CUR_PRTIFO PRODUCTINFO%ROWTYPE;
 8 
 9   CURSOR CUR_CATEGORY --产品表中的产品类型游标    第9~11行表示创建游标cur_category;
10   IS
11     SELECT CATEGORY FROM PRODUCTINFO GROUP BY CATEGORY;
12 
13   CURSOR CUR_PROINFO(CTGY VARCHAR) IS     第13~19行表示创建游标CUR_PROINFO;该游标带有参数,其参数代表产品类型的编码。游标根据产品的类型不同,获取产品类型中价格最低的数据。
14     SELECT *
15       FROM (SELECT *
16               FROM PRODUCTINFO
17              WHERE CATEGORY = CTGY
18              ORDER BY PRODUCTPRICE ASC)
19      WHERE ROWNUM < 2;
20 
21 BEGIN
22   SELECT COUNT(1)      第22~25表示判断临时表productinfo_tmp是否存在。此处利用select into语句把结果放到变量tabext中,如果该表存在结果为1,否则为0.tabext变量将在第37行使用。
23     INTO TABEXT
24     FROM ALL_TABLES
25    WHERE TABLE_NAME = 'productinfo_tmp';
26 
27   PC_DELESTR   := 'delete from productinfo_tmp';   第27行表示为变量pc_delestr赋值,他的值是一条SQL语句,该SQL语句表示删除表productinfo_tmp中的数据。这种写法常常用在动态SQL语句上。
28   PC_CREATESTR := 'create global temporary table productinfo_tmp   第28行表示为变量pc_createstr赋值。他的值是一条DDL语句,该语句用来创建临时表productinfo_tmp。
29   (productid varchar2(10) not null,
30   productname varchar2 (20),
31   productprice number(8,2),
32   quantity number(10),
33   category varchar2(10),
34   desperaction varchar2(1000),
35   origin varchar2(10))on commit preserve rows';
36 
37   IF TABEXT = 0 THEN    第37~44行完成分析步骤中的第一步:创建临时表productinfo_tmp。首先判断临时表是否存在,如果不存在,则创建,如果存在则删除表中数据。这里使用了execute immediate语句,利用它执行DDL语句及动态语句。
38     --不存在临时表就创建一个
39     EXECUTE IMMEDIATE PC_CREATESTR;
40     DBMS_OUTPUT.PUT_LINE('创建临时表成功!');
41   ELSE
42     EXECUTE IMMEDIATE PC_DELESTR;
43     DBMS_OUTPUT.PUT_LINE('删除记录完成!');
44   END IF;
45   OPEN CUR_CATEGORY;   第45~49行表示打开游标cur_category,并进入流循环取值。当游标的%nofound属性为true时退出。
46   LOOP
47     FETCH CUR_CATEGORY
48       INTO CUR_CTGY;
49     EXIT WHEN CUR_CATEGORY%NOTFOUND;
50     OPEN CUR_PROINFO(CUR_CTGY);   第50~53行表示打开游标cur_proinfo,它的参数是cur_category中的结果。
51     FETCH CUR_PROINFO
52       INTO CUR_PRTIFO;
53     IF CUR_PROINFO%FOUND THEN
54       IF CUR_PRTIFO.PRODUCTPRICE < 20 THEN  第54~58行表示判断价格是否低于20,如果低于20输出到屏幕。
55         ---产品价格低于20
56         DBMS_OUTPUT.PUT_LINE('产品ID' || CUR_PRTIFO.PRODUCTID || '产品名称' ||
57                              CUR_PRTIFO.PRODUCTNAME || '产品价格' ||
58                              CUR_PRTIFO.PRODUCTPRICE);
59       ELSE
60         --非低于20价格的产品输入到临时表productinfo_tmp   第60~69行表示如果非低于20的插入表productinfo_tmp中。
61         EXECUTE IMMEDIATE 'insert into productinfo_tmp(
62         productid,productname,productprice,quantity,category,desperaction,origin) values
63         (''' || CUR_PRTIFO.PRODUCTID || ''',''' ||
64                           CUR_PRTIFO.PRODUCTNAME || ''',''' ||
65                           CUR_PRTIFO.PRODUCTPRICE || ''',''' ||
66                           CUR_PRTIFO.QUANTITY || ''',''' ||
67                           CUR_PRTIFO.CATEGORY || ''',''' ||
68                           CUR_PRTIFO.DESPERACTION || ''',''' ||
69                           CUR_PRTIFO.ORIGIN || ''')';
70       END IF;
71     END IF;
72     CLOSE CUR_PROINFO;
73   END LOOP;
74   COMMIT;
75   CLOSE CUR_CATEGORY;
76   EXECUTE IMMEDIATE 'update productinfo_tmp set desperaction = ''热销产品''';   第76行表示将productinfo_tmp表中的数据修改为热销产品。
77 END;

【执行】

SQL>exec PRODUCT_TEMP_UPDATE_PRC ;

你可能感兴趣的:(Oracle)