oracle:oracle函数

这个世界上肯定有另一个我,做着我不敢做的事,过着我想过的生活。挑战自己不擅长的事,敢于说走就做的旅行,每天做很多新鲜的事。极致的幸福,存在于孤独的深海。在这样日复一日的生活里,我逐渐和自己达成和解。

1. ORACLE的启动和关闭

1、在单机环境下

要想启动或关闭ORACLE系统必须首先切换到ORACLE用户,如下

su - oracle 

a、启动ORACLE系统

oracle>svrmgrl 
SVRMGR>connect internal 
SVRMGR>startup 
SVRMGR>quit 

b、关闭ORACLE系统

oracle>svrmgrl 
SVRMGR>connect internal 
SVRMGR>shutdown 
SVRMGR>quit 

启动oracle9i数据库命令:

$ sqlplus /nolog 
SQL*Plus: Release 9.2.0.1.0 - Production on Fri Oct 31 13:53:53 2003 
Copyright (c) 1982, 2002, Oracle Corporation.  All rights reserved. 
SQL> connect / as sysdba  
Connected to an idle instance. 
SQL> startup^C 
SQL> startup 
ORACLE instance started. 

2、在双机环境下

要想启动或关闭ORACLE系统必须首先切换到root用户,如下 su - root a、启动ORACLE系统 hareg -y oracle b、关闭ORACLE系统 hareg -n oracle Oracle数据库有哪几种启动方式

2. 导入数据

C:\Users\tony>sqlldr
SQL*Loader: Release 11.2.0.1.0 - Production on 星期六 9月 3 09:12:45 2011
Copyright (c) 1982, 2009, Oracle and/or its affiliates.  All rights reserved.
用法: SQLLDR keyword=value [,keyword=value,...]
有效的关键字:
    userid -- ORACLE 用户名/口令
   control -- 控制文件名
       log -- 日志文件名
       bad -- 错误文件名
      data -- 数据文件名
   discard -- 废弃文件名
discardmax -- 允许废弃的文件的数目         (全部默认)
      skip -- 要跳过的逻辑记录的数目  (默认 0)
      load -- 要加载的逻辑记录的数目  (全部默认)
    errors -- 允许的错误的数目         (默认 50)
      rows -- 常规路径绑定数组中或直接路径保存数据间的行数
               (默认: 常规路径 64, 所有直接路径)
  bindsize -- 常规路径绑定数组的大小 (以字节计)  (默认 256000)

    silent -- 运行过程中隐藏消息 (标题,反馈,错误,废弃,分区)
    direct -- 使用直接路径                     (默认 FALSE)
   parfile -- 参数文件: 包含参数说明的文件的名称
  parallel -- 执行并行加载                    (默认 FALSE)
使用的默认的, 没有加入 direct=true . 
执行的脚本类似: 
$ sqlldr   [email=user1/passwd1@db1]user1/passwd1@db1[/email]   control=xxx.ctl

3. 函数与存储过程

1. 函数demo:

create or replace procedure sy_merge_label(
      par1 varchar2 in,
      par2 varchar2 out
) as

 CURSOR C_LABEL IS
  select rownum,ENT_MD5,ENT_LABEL from crt_ent_label group by ENT_MD5;
 C_ROW C_LABEL%ROWTYPE;
 rown int;
 md5 varchar2;
 md5_old int:=0;
 label varchar2; 
 TYPE arry_num IS VARRAY(100) OF NUMBER; 
 rownums arry_num; 

begin

 FOR C_ROW IN C_LABEL LOOP
  --处理逻辑
  rown:=C_ROW.rownum;
  md5:= C_ROW.ENT_MD5;
  label:=C_ROW.ENT_LABEL;
  if label in ('医学考试') then
    --if md5_old != md5 then
    
    --else
      
    --DBMS_OUTPUT.PUT_LINE(md5||label)
  end if  
 END LOOP

EXCEPTION  
  WHEN no_data_found THEN  
    raise_application_error(-20000, '该员工不存在');  

end sy_merge_label 

2. 解释: PL/SQL中的过程和函数(通常称为子程序)是PL/SQL块的一种特殊的类型,这种类型的子程序可以以编译的形式存放在数据库中,并为后续的程序块调用。

相同点: 完成特定功能的程序

不同点:是否用return语句返回值。 举个例子:

create or replace procedure PrintStudents(p_staffName in xgj_test.username%type) as
 
 cursor c_testData is
 select t.sal, t.comm from xgj_test t where t.username = p_staffName;
 
begin
 
 for v_info in c_testData loop
 DBMS_OUTPUT.PUT_LINE(v_info.sal || ' ' || v_info.comm);
 end loop;
 
end PrintStudents;

一旦创建了改程序并将其存储在数据库中,就可以使用如下的方式调用该过程

begin
 PrintStudents('Computer Science');
 PrintStudents('Match');
end;
/

或者

exec PrintStudents('Computer Science');
exec PrintStudents('Match');
 

在命令窗口中: oracle

在pl/sql工具的sql窗口中: oracle

** 存储过程的创建和调用

基本语法 **

create [ or replace] procedure procedure_name
[( argument [ {IN | OUT | IN OUT }] type,
......
argument [ {IN | OUT | IN OUT }] type ) ] { IS | AS}
procedure_body

无参的存储过程

/**
 无参数的存过
 打印hello world
 
 调用存储过程:
 1. exec sayhelloworld();
 2 begin
 sayhelloworld();
 end;
 /
 
*/
create or replace procedure sayhelloworld
as
--说明部分
begin
 dbms_output.put_line('hello world');
end sayhelloworld;

调用过程:

SQL> set serveroutput on ;
SQL> exec sayhelloworld();
 
hello world
 
PL/SQL procedure successfully completed
 
SQL> begin
 2 sayhelloworld();
 3 sayhelloworld();
 4 end;
 5 /
 
hello world
hello world
 
PL/SQL procedure successfully completed

带参数的存储过程

/**
创建一个带参数的存储过程
给指定的员工增加工资,并打印增长前后的工资 
*/
create or replace procedure addSalary(staffName in xgj_test.username%type )
as
--定义一个变量保存调整之前的薪水
oldSalary xgj_test.sal%type;
 
begin
 --查询员工涨之前的薪水
 select t.sal into oldSalary from xgj_test t where t.username=staffName; 
 
 --调整薪水
 update xgj_test t set t.sal = sal+1000 where t.username=staffName ;
 
 --输出
 dbms_output.put_line('调整之前的薪水:'|| oldSalary || ' ,调整之后的薪水:' || (oldSalary + 1000));
 
end addSalary;

可以看到,update语句之后并没有commit的操作。

一般来讲为了保证事务的一致性,由调用者来提交比较合适,当然了是需要区分具体的业务需求的~

begin
addSalary('xiao');
addSalary('gong');
commit ;
end ;
/

2.存储函数

基本语法

create [ or replace] function function_name
[( argument [ {IN | OUT | IN OUT }] type,
......
argument [ {IN | OUT | IN OUT }] type ) ] 
RETURN { IS | AS}
function_body

其中 return子句是必须存在的,一个函数如果没有执行return就结束将发生错误,这一点和存过有说不同

oracle

/**
查询员工的年薪 (月工资*12 + 奖金)
*/
 
create or replace function querySalaryInCome(staffName in varchar2)
 
 return number as
 --定义变量保存员工的工资和奖金
 pSalary xgj_test.sal%type;
 pComm xgj_test.comm%type;
 
begin
 --查询员工的工资和奖金
 select t.sal, t.comm
 into pSalary, pComm
 from xgj_test t
 where t.username = staffName;
 --直接返回年薪
 return pSalary * 12 + pComm;
end querySalaryInCome;

orcle

存在一个问题,当奖金为空的时候,算出来的年收入竟然是空的。

因为 如果一个表达式中有空值,那么这个表达式的结果即为空值。

所以我们需要对空值进行处理, 使用nvl函数即可。

最后修改后的function为

create or replace function querySalaryInCome(staffName in varchar2)
 
 return number as
 --定义变量保存员工的工资和奖金
 pSalary xgj_test.sal%type;
 pComm xgj_test.comm%type;
 
begin
 --查询员工的工资和奖金
 select t.sal, t.comm
 into pSalary, pComm
 from xgj_test t
 where t.username = staffName;
 --直接返回年薪
 return pSalary * 12 + nvl(pComm,0);
end querySalaryInCome;

out参数 一般来讲,存储过程和存储函数的区别在于存储函数可以有一个返回值,而存储过程没有返回值。 1.存储过程和存储函数都可以有out参数 2.存储过程和存储函数都可以有多个out参数 3.存储过程可以通过out参数实现返回值

那我们如何选择存储过程和存储函数呢?

原则:

如果只有一个返回值,用存储函数,否则(即没有返回值或者有多个返回值)使用存储过程。

/**
根据员工姓名,查询员工的全部信息
*/
create or replace procedure QueryStaffInfo(staffName in xgj_test.username%type,
           pSal out number,
           pComm out xgj_test.comm%type,
           pJob out xgj_test.job%type) 
 
is
 
begin
 --查询该员工的薪资,奖金和职位
 select t.sal,t.comm,t.job into pSal,pComm,pJob from xgj_test t where t.username=staffName;
end QueryStaffInfo;

oracle

先抛出两个思考问题: 1.查询员工的所有信息–> out参数太多怎么办? 2.查询某个部门中所有员工的信息–> out中返回集合?

后面会讲到如何解决? 总不能一个个的写out吧~

3. 在应用中访问存储过程和存储函数

详情请访问原文链接

总结

整个文章的基本组织结构依照典型的工科思维方式进行串接,即从理论到实践。

comments powered by Disqus