Oracle存储过程例子游标异常

时间:2021-07-14 08:13:47
四种情况:有无参数、有无输出
SQL中调用存储过程语句:call procedure_name();
注:调用时”()”是不可少的,无论是有参数还是无参数.
            
定义对数据库存储过程的调用时
1、无参数存储过程:{call procedure_name}
2、仅有输入参数的存储过程:{call procedure_name(?,?...)}。
这里?表示输入参数,创建存储过程时用in表示输入参数
3、仅有输出参数的存储过程:{call procedure_name(?,?...)}。
这里的?表示输出参数,创建存储过程时用out表示输出参数
4、既有输入参数又有输出参数的存储过程{call procedure_name(?,?...)}。
这里的?有表示输出参数的,也有表示输入参数的
           
下面将会对这4种情况分别举出实例!!!
1、无参数存储过程
CREATE OR REPLACE PROCEDURE stu_proc AS
    --声明语句段
    v_name VARCHAR2(20);
BEGIN
    --执行语句段
    SELECT o.sname INTO v_name FROM student o WHERE o.id=4;
    dbms_output.put_line(v_name);
EXCEPTION
    --异常处理语句段
    WHEN NO_DATA_FOUND THEN dbms_output.put_line('NO_DATA_FOUND');
END;

2、仅带入参的存储过程
CREATE OR REPLACE PROCEDURE stu_proc(v_id IN student.id%type) AS
    --声明语句段
    v_name varchar2(20);
BEGIN
    --执行语句段
    SELECT o.sname INTO v_name FROM student o where o.id=v_id;
    dbms_output.put_line(v_name);
EXCEPTION
    --异常处理语句段
    WHEN NO_DATA_FOUND THEN dbms_output.put_line('NO_DATA_FOUND');
END;

3、仅带出参的存储过程 
--此种存储过程不能直接用call来调用,这种情况的调用将在下面oracle函数调用中说明
CREATE OR REPLACE PROCEDURE stu_proc(v_name OUT student.sname%type) AS
    --声明语句段
BEGIN
    --执行语句段
    SELECT o.sname INTO v_name FROM student o where o.id=1;
    dbms_output.put_line(v_name);
EXCEPTION
    --异常处理语句段
    WHEN NO_DATA_FOUND THEN dbms_output.put_line('NO_DATA_FOUND');
END;

4、带入参和出参的存储过程
--此种存储过程不能直接用call来调用,这种情况的调用将在下面oracle函数调用中说明
CREATE OR REPLACE PROCEDURE stu_proc(v_id IN student.id%type, v_name OUT student.sname%type) AS
    --声明语句段
BEGIN
    --执行语句段
    SELECT o.sname INTO v_name FROM student o where o.id=v_id;
    dbms_output.put_line(v_name);
EXCEPTION
    --异常处理语句段
    WHEN NO_DATA_FOUND THEN dbms_output.put_line('NO_DATA_FOUND');
END;

----------------------------------------------------------分割线-------------------------------------------------------------------
Java代码   Oracle存储过程例子游标异常
  1. Qracle PL/SQL  
  2. --存储过程  
  3. 1.PL/SQL  
  4.   
  5.   SQL是数据库普通话,每个数据库在实现SQL国际标准之外,也有自己特有的语句。(Hibernate dialect)  
  6.   通讯的标准:ODBC(ado , ado.net),JDBC(jdo , Hibernate)  
  7.               ODBC、JDBC是最有效率的,但是开发繁琐,才有后来括号中的高度函数化的拓展  
  8.   
  9.   PL/SQL:Procudural Language Extension to SQL.  
  10.          在SQL语句基础上,加上了结构化流程控制,可用多条SQL语句完成一个功能。  
  11.          PL/SQL功能强大,经常用来书写复杂的业务逻辑。  
  12.   语法:  
  13.     set serveroutput on;    //打开控制台输出  
  14.     declare [变量名] [变量数据类型];  //定义变量,写在begin之前  
  15.     begin  
  16.         //代码块  
  17.     end;     //代码编辑区  
  18.     :=    //赋值符号   
  19.     dbms_output.put_line('内容'||变量);   //控制台输出,和Java不同的是连接使用的是||符号而不是加  
  20.   
  21. 号,注意字符串必须用单引号来修饰  
  22.   
  23.   范例:  
  24.     declare result int;  
  25.     begin  
  26.       select x into result from ttt where rownum=1;  
  27.       result:=result+1;  
  28.       dbms_output.put_line('result='||result);  
  29.     end;  
  30.   
  31.   
  32. 学生表的创建  
  33. create table my_student  
  34. (  
  35.   stuno int primary key,  
  36.   stuname varchar2(20) not null,  
  37.   stuage  int not null  
  38. )  
  39. 范例2  
  40. declare  
  41.   v_stuname varchar2(20);  
  42.   v_stuage int;  
  43. begin  
  44.   select stuname, stuage into v_stuname,v_stuage  
  45.   from my_student  
  46.   where stuno=2;  
  47.   dbms_output.put_line('sutdent name'||v_stuname||', student age:'||v_stuage);  
  48.     
  49.   exception  
  50.     when NO_DATA_FOUND then  
  51.       dbms_output.put_line('There is no student with stu no 2');  
  52. end;   
  53.   
  54. 范例3:  
  55. new -> program window ->procedure  
  56.   
  57. --根据学号显示对应学生信息  
  58. create or replace procedure uuu_show_student(x_stuno in int)   
  59. is  
  60.   v_stuname varchar2(20);  
  61.   v_stuage int;  
  62. begin  
  63.   select stuname, stuage into v_stuname,v_stuage  
  64.   from my_student  
  65.   where stuno=x_stuno;  
  66.   dbms_output.put_line('sutdent name'||v_stuname||', student age:'||v_stuage);  
  67.     
  68.   exception  
  69.     when NO_DATA_FOUND then  
  70.       dbms_output.put_line('There is no student with stu no 2');  
  71.           
  72. end uuu_show_student;  
  73.   
  74. 运行存储过程  
  75. 执行execute uuu_show_student;  
  76.   
  77. 范例4.两数求和  
  78. create or replace procedure show_uuu_number(x_num1 in int,x_num2 in int)  
  79. is  
  80. x_big_number int;  
  81. x_num_index int;  
  82. begin  
  83.   if x_num1 > x_num2 then  
  84.      x_big_number := x_num1;  
  85.      x_num_index := 1;  
  86.   else  
  87.      x_big_number := x_num2;  
  88.      x_num_index := 2;  
  89.   end if;  
  90.     
  91.   dbms_output.put_line('big number:'||x_big_number||' index:'||x_num_index);  
  92. end show_uuu_number;  
  93.   
  94. 范例5.循环分支  
  95.   
  96. create or replace procedure show_uuu_number(x_num1 in int,x_num2 in int)  
  97. is  
  98. x_big_number int;  
  99. x_num_index int;  
  100. begin  
  101.   if x_num1 > x_num2 then  
  102.      x_big_number := x_num1;  
  103.      x_num_index := 1;  
  104.   elsif x_num1 > x_num2 then  
  105.      x_big_number := x_num2;  
  106.      x_num_index := 2;  
  107.   else   
  108.      dbms_output.put_line('equal');  
  109.   end if;  
  110.     
  111.   if x_num1 <> x_num2 then    
  112.      dbms_output.put_line('big number:'||x_big_number||' index:'||x_num_index);  
  113.   end if;  
  114. end show_uuu_number;  
  115.   
  116.   
  117. case  
  118.      when....  
  119.      when....  
  120.      else  
  121.         .....  
  122.   and case;  
  123.   
  124. 范例6  
  125. 有返回值的用function  
  126.   
  127. 计算三角形面积  
  128. create or replace function uuu_area(width in number,height in number) return number is  
  129.   Result number;  
  130. begin  
  131.   Result := 0.5*width*height;  
  132.   return(Result);  
  133. end uuu_area;  
  134. 运行函数  
  135. select uuu_area(3,5) from dual;  
  136.   
  137. uuu_AREA(3,5)  
  138. -------------  
  139.            15  
  140.   
  141. 范例7  
  142. case  
  143.      when....  
  144.      when....  
  145.      else  
  146.         .....  
  147.   and case;  
  148. 应用  
  149.   
  150. create or replace function show_uuu_day(datestr in varchar2)  
  151.   return varchar2 is  
  152.   Result    varchar2(200);  
  153.   checkdate date;  
  154.   v_day     varchar2(1);  
  155. begin  
  156.   checkdate := to_date(trim(datestr), 'YYYY-MM-DD');  
  157.   v_day     := to_char(checkdate, 'D');  
  158.   
  159.   case v_day  
  160.     when '1' then  
  161.       Result := datestr || '是星期天';  
  162.     when '2' then  
  163.       Result := datestr || '是星期一';  
  164.     when '3' then  
  165.       Result := datestr || '是星期二';  
  166.     when '4' then  
  167.       Result := datestr || '是星期三';  
  168.     when '5' then  
  169.       Result := datestr || '是星期四';  
  170.     when '6' then  
  171.       Result := datestr || '是星期五';  
  172.     when '7' then  
  173.       Result := datestr || '是星期六';  
  174.     else  
  175.       dbms_output.put_line(datestr || '是星期六');  
  176.   end case;  
  177.   
  178.   return(Result);  
  179. end show_uuu_day;  
  180.   
  181. 执行函数  
  182. SQL> select show_uuu_day('2010-11-4') from dual;  
  183.    
  184. SHOW_uuu_DAY('2010-11-4')  
  185. --------------------------------------------------------------------------------  
  186. 2010-11-4是星期四  
  187.   
  188. 范例8  
  189. 循环结构  
  190.   
  191. create or replace function uuu_get_sum(num1 in number, num2 in number) return number is  
  192.   Result number := 0;  
  193.   temp number;  
  194. begin  
  195.   temp := num1;  
  196.   loop  
  197.     Result:=Result+temp;  
  198.     temp:=temp+1;  
  199.    -- if temp > num2 then  
  200.    --   exit;  
  201.     --end if;  
  202.   exit when temp > num2;  
  203.   end loop;  
  204.   return(Result);  
  205. end uuu_get_sum;  
  206.   
  207. 执行函数  
  208. SQL> select uuu_get_sum(1,100) from dual;  
  209.    
  210. uuu_GET_SUM(1,100)  
  211. ------------------  
  212.               5050  
  213.   
  214. while loop   
  215. 例:  
  216. create or replace function uuu_get_sum(num1 in number, num2 in number) return   
  217.   
  218. number is  
  219.   Result number := 0;  
  220.   temp number;begin  
  221.   temp := num1;  
  222.   while num2 <= 200 loop  
  223.     Result:=Result+temp;  
  224.     temp:=temp+1;  
  225.    -- if temp > num2 then  
  226.    --   exit;  
  227.     --end if;  
  228.   exit when temp > num2;  
  229.   end loop;  return(Result);  
  230. end uuu_get_sum;  
  231.   
  232. 执行函数  
  233. SQL> select uuu_get_sum(1,1000) from dual;  
  234.    
  235. uuu_GET_SUM(1,1000)  
  236. -------------------  
  237.                   0  
  238.   
  239.   
  240. 范例8  
  241. 数字for loop循环  
  242.   
  243. create or replace procedure sum(begin1 number,end2 number)  
  244. as   
  245.   tosum number;  
  246. begin  
  247.  tosum:=0;  
  248.  for i in begin1..end2  
  249.  loop  
  250.     tosum:=tosum+i;  
  251.  end loop;  
  252.  dbms_output.put_line(tosum);  
  253. end sum;  
  254.   
  255.   
  256. 001.判断一个数是否为质数  
  257.   
  258. create or replace function x_isprime(num in intreturn int is  
  259.   Result int;  
  260. begin  
  261. for i in 2..num-1  
  262.    loop  
  263.     if num mod i = 0 then  
  264.         Result := 0;  
  265.         return(Result);  
  266.     end if;      
  267.   end loop;  
  268.   if num >= 2 then   
  269.     Result := 1;  
  270.   end if;  
  271.   return(Result);  
  272. end x_isprime;  
  273.   
  274. 002判断质数  
  275.   
  276. create or replace procedure x_prime(begini in int, endi in int)   
  277. is  
  278. count2 int := 0;  
  279. begin  
  280.   for i in begini..endi  
  281.   loop  
  282.     if x_isprime(i) = 1 then  
  283.      dbms_output.put(i||'  ');  
  284.      count2:=count2+1;  
  285.      if count2 mod 8 = 0 then  
  286.         dbms_output.put_line('');  
  287.      end if;  
  288.     end if;  
  289.   end loop;  
  290. end x_prime;  
  291.   
  292.   
  293. ======  
  294. debug 权限设置  
  295. grant debug connect session to test1;  
  296.   
  297. 003判断质数  
  298. =======  
  299. CREATE OR REPLACE PROCEDURE show_prime(bval IN INT, eval IN INT) IS  
  300.   flag INT;  
  301.   icount int:=0;  
  302. BEGIN  
  303.   -- 取数循环  
  304.   FOR i IN bval .. eval LOOP  
  305.     -- 质数判断循环  
  306.     flag := 1;  
  307.     FOR j IN 2 .. i - 1 LOOP  
  308.       IF i MOD j = 0 THEN  
  309.         flag := 0;  
  310.         EXIT;  
  311.       END IF;  
  312.     END LOOP;  
  313.     
  314.     IF flag = 1 THEN  
  315.       dbms_output.put(i||'  ');  
  316.       icount:=icount+1;  
  317.       if icount mod 8 =0 then  
  318.          dbms_output.put_line('');  
  319.       end if;  
  320.     END IF;  
  321.     
  322.   END LOOP;  
  323. END show_prime;  
  324.   
  325. ======================================================================  
  326. --游标  
  327. pl/sql cursor 操作  
  328.   
  329. 1. 什么是游标?  
  330.    oracle在执行一条SQL语句的时候,它将创建一个内存区域 (context area),该内存区域包含执行这条语句所需要的所有信息。  
  331.    信息如下:  
  332.      1. 该语句执行之后返回的记录集  
  333.      2. 一个指针,指向了该语句在内存中的被解析后的结果。  
  334.   
  335.    cursor(游标) 是一个handle (pointer), 指向了这个上下文区域。  
  336.   
  337.       
  338.    通过cursor, PL/SQL程序能够控制context area, 掌握在语句运行的时,将如何对该区域产生影响。  
  339.   
  340. 2. 游标的类型  
  341.    1) implicit cursor  
  342.       每条SQL语句执行的时候,将自动产生一个implicit游标。 该游标,用户不可控制。  
  343.   
  344.       一个cursor将自动和每条DML语句关联 (update,delete,insert), 我们可以通过cursor了解上头语句产生的结果。  
  345.   
  346.       所有update和delete语句相关联cursor,包含了该操作影响的行的集合。  
  347.   
  348.       最后打开的cursor, 名字叫SQL cursor.  
  349.   
  350.       --------------------------------------------------------------------------------------------  
  351.       update my_student set stuname='mary' where stuno=60;  
  352.       dbms_output.put_line(SQL%ROWCOUNT);  
  353.   
  354.    2) explicit cursor  
  355.       用户自己定义的游标,针对的是返回超过一条记录的查询。 用户可以通过该cursor控制记录返回过程。  
  356.   
  357.   
  358.   
  359.       Record Type  
  360.       记录是复杂的数据结构。记录往往表现成为表的一行。  
  361. create or replace procedure show_student2 is  
  362.    vr_student my_student%ROWTYPE;  
  363. begin  
  364.    select *   
  365.    into vr_student  
  366.    from my_student where stuno=6;  
  367.      
  368.    dbms_output.put_line(vr_student.stuno||','||vr_student.stuname);  
  369.      
  370. end show_student2;  
  371.         
  372.   
  373.       a. 声明游标 (declare a cursor)  
  374.          该操作初始化这个游标,为其创建内存空间。  
  375.            
  376.          CURSOR c_cursor_name is select statement  
  377.          (该游标和select语句相关联)  
  378.         
  379.          ------------------  
  380.          declare   
  381.            v_name varchar2(20);  
  382.            CURSOR c_mycursor is   
  383.               select * from student where name like '%h%';  
  384.   
  385.          游标打开后,不能继续再二次打开。  
  386.   
  387.         
  388.       b. 打开游标 (open cursor)  
  389.          创建context area, 执行语句, 获得rows.           
  390.   
  391.            open c_mycursor  
  392.   
  393.       c. 获取cursor中的行。     
  394.            
  395.          fetch cursorname into pl/sql variables  
  396.          fetch cursorname into pl/sql record  
  397.   
  398.       d. 关闭cursor  
  399.          一旦所有的行被处理结束,cursor应该被关闭。   
  400.          关闭的操作通知pl/sql engine, 程序对该cursor的需求已经结束,可以释放context are所占用的内存资源。     
  401.   
  402.   
  403.          cursor一旦关闭,则不可以继续fetch . 也不能重复关闭cursor.  
  404.   
  405.     > 常用的cursor属性  
  406.       cursorname%NOTFOUND  
  407.       cursorname%FOUND  
  408.       cursorname%ROWCOUNT  
  409.       cursorname%ISOPEN  
  410.   
  411.  --------------------  
  412. create or replace procedure show_student2 is  
  413.    CURSOR c_student is   
  414.        select * from my_student order by stuno desc;  
  415.    vr_student my_student%ROWTYPE;  
  416.      
  417.    TYPE simple_stu is record  
  418.      (  
  419.        stuname my_student.stuname%TYPE,  
  420.        stuage  my_student.stuage%TYPE,  
  421.        stuage2 int  
  422.       );  
  423.     vr_simple_student simple_stu;  
  424.     cursor c_simple_student is  
  425.         select stuname,stuage,stuage+2 from my_student order by stuno desc;  
  426. begin  
  427. /* 
  428.    select *  
  429.    into vr_student 
  430.    from my_student where stuno=6; 
  431.     
  432.    dbms_output.put_line(vr_student.stuno||','||vr_student.stuname); 
  433. */  
  434.     
  435.    open c_student;  
  436.       
  437.    loop  
  438.      fetch c_student into vr_student;  
  439.      exit when c_student%NOTFOUND;  
  440.      dbms_output.put_line(vr_student.stuno||','||vr_student.stuname);  
  441.    end loop;  
  442.      
  443.    if c_student %ISOPEN then   
  444.       close c_student;     
  445.    end if;  
  446.      
  447.    open c_simple_student;  
  448.    loop  
  449.      fetch c_simple_student into vr_simple_student;  
  450.      exit when c_simple_student%NOTFOUND;  
  451.      dbms_output.put_line(vr_simple_student.stuname||','||vr_simple_student.stuage  
  452.                                  ||','||vr_simple_student.stuage2);  
  453.    end loop;  
  454.    close c_simple_student;  
  455.      
  456. end show_student2;  
  457.   
  458. --------------------------------------------  
  459.   
  460. cursor for loop   
  461. nested cursor  
  462.   
  463. DECLARE  
  464.   v_sid student.student_id%TYPE;  
  465.   CURSOR c_student IS  
  466.     SELECT student_id, first_name, last_name  
  467.       FROM student  
  468.      WHERE student_id < 110;  
  469.   CURSOR c_course IS  
  470.     SELECT c.course_no, c.description  
  471.       FROM course c, section s, enrollment e  
  472.      WHERE c.course_no = s.course_no  
  473.        AND s.section_id = e.section_id  
  474.        AND e.student_id = v_sid;  
  475. BEGIN  
  476.   /* 
  477.    使用for loop cursor, 可以便捷的遍历游标,省去了open,fetch,close的书写。 
  478.     连保存变量的定义也可以省略,可在for后直接书写变量名。 
  479.   */  
  480.   FOR r_student IN c_student LOOP  
  481.     v_sid := r_student.student_id;  
  482.     DBMS_OUTPUT.PUT_LINE(chr(10));  
  483.     DBMS_OUTPUT.PUT_LINE(' The Student ' || r_student.student_id || ' ' ||  
  484.                          r_student.first_name || ' ' ||  
  485.                          r_student.last_name);  
  486.     DBMS_OUTPUT.PUT_LINE(' is enrolled in the ' || 'following courses: ');  
  487.     -- nested cursor  
  488.     FOR r_course IN c_course LOOP  
  489.       DBMS_OUTPUT.PUT_LINE(r_course.course_no || ' ' ||  
  490.                            r_course.description);  
  491.     END LOOP;  
  492.   END LOOP;  
  493. END;  
  494.   
  495. ---------------------------------------------------------------  
  496. 带参数的游标  
  497.   
  498.    CURSOR c_student(p_stuage in my_student.stuage%type) is   
  499.        select * from my_student where stuage=p_stuage order by stuno desc;  
  500.    
  501.   
  502.    for vr_student in c_student(20)   
  503.    loop  
  504.      dbms_output.put_line(vr_student.stuno||','||vr_student.stuname);  
  505.    end loop;  
  506.   
  507.   CURSOR c_student2(p_stuage in my_student.stuage%type,p_stuname in my_student.stuname%TYPE) is   
  508.        select * from my_student where stuage=p_stuage order by stuno desc;  
  509.      
  510. cursor具备的参数:  
  511.  1) cursor得到了复用。  
  512.  2) 提高了性能,压缩了返回的行的数量。  
  513.   
  514. ====================================================================  
  515.   
  516. --异常  
  517. 1.PL/SQL Exception  
  518.   常用的预定义异常  
  519.   a)NO_DATA_FOUND  
  520.     根据查询条件,没有查询记录被找到  
  521.   b)TOO_MANY_ROWS  
  522.      select into 结构只能返回一条记录,赋予存储过程变量。如果select              ..into..结构返回记录为多条,将产生这个异常   
  523.   c)ZERO_DIVIDE  
  524.     除数是0(把ORA-01476 error映射成ZERO_DIVIDE错误)  
  525.     例: SQL> select 6/0 from dual;  
  526.       select 6/0 from dual  
  527.       ORA-01476: 除数为 0  
  528.   d)VALUE_ERROR  
  529.     从运算或者数据库中取得值赋予变量的时候类型不匹配或者长度不足,导致的异常  
  530.   e)DUP_VAL_ON_INDEX  
  531.       主键不可重复,违反主键唯一约束  
  532.   f)OTHERS  
  533.      (类似java Exception异常)  
  534.   
  535. 数据库表  
  536. create table my_student(  
  537.   stuno int primary key,  
  538.   stuname varchar2(20),  
  539.   stuage int  
  540. );  
  541. insert into my_student values(1,'dadiv',20);  
  542. insert into my_student values(2,'mary',20);  
  543. insert into my_student values(3,'henry',20);  
  544. 异常举例例子:  
  545. create or replace procedure uuu_show_student(x_stuno in int)  
  546. is  
  547.   v_stuname varchar2(20);--替换v_stuname varchar2(2)/int值不匹配或者长度不足异常  
  548.   v_stuage int;  
  549. begin  
  550.   insert into my_student values(2,'kate',49);--DUP_VAL_ON_INDEX异常  
  551.   select stuname, stuage into v_stuname,v_stuage  
  552.   from my_student  
  553.   where stuno=x_stuno;--加上or stuname like '%y'产生值记录太多异常  
  554.   dbms_output.put_line('sutdent name'||v_stuname||', student age:'||v_stuage);  
  555.     
  556.   exception  
  557.     when NO_DATA_FOUND then  
  558.       dbms_output.put_line('There is no student with stu no '||x_stuno);  
  559.     when VALUE_ERROR then  
  560.       dbms_output.put_line('值不匹配');  
  561.     when TOO_MANY_ROWS then  
  562.       dbms_output.put_line('记录太多');  
  563.     when DUP_VAL_ON_INDEX then  
  564.       dbms_output.put_line('主键不可重复,插入失败');  
  565.     when OTHERS then   
  566.       dbms_output.put_line('其它异常捕获');--一些预定义异常的父类  
  567.           
  568. end uuu_show_student;  
  569.       
  570.   
  571. 异常的作用域  
  572.   
  573.   DECLARE  
  574.     v_student_id NUMBER := &sv_student_id;  
  575.     v_name VARCHAR2(30);  
  576.     v_total NUMBER(1);  
  577.     -- outer block  
  578.       
  579.     BEGIN  
  580.       SELECT RTRIM(first_name)||' '||RTRIM(last_name)  
  581.       INTO v_name  
  582.       FROM student  
  583.       WHERE student_id = v_student_id;  
  584.       DBMS_OUTPUT.PUT_LINE ('Student name is '||v_name);  
  585.       -- inner block  
  586.       BEGIN  
  587.         SELECT COUNT(*)  
  588.         INTO v_total  
  589.         FROM enrollment  
  590.         WHERE student_id = v_student_id;  
  591.         DBMS_OUTPUT.PUT_LINE ('Student is registered for '||  
  592.         v_total||' course(s)');  
  593.         EXCEPTION  
  594.         WHEN VALUE_ERROR OR INVALID_NUMBER THEN  
  595.         DBMS_OUTPUT.PUT_LINE ('An error has occurred');  
  596.       END;  
  597.         
  598.       EXCEPTION  
  599.       WHEN NO_DATA_FOUND THEN  
  600.       DBMS_OUTPUT.PUT_LINE ('There is no such student');  
  601. END;   
  602.   
  603. 自定义异常:  
  604.   
  605. 例:  
  606. create or replace procedure uuu_show_student(x_stuno in int)  
  607. is  
  608.   v_stuname varchar2(20);--替换v_stuname varchar2(2)/int值不匹配或者长度不足异常  
  609.   v_stuage int;  
  610.   e_invalid_stuno EXCEPTION;--自定义异常  
  611. begin  
  612.   if x_stuno < 0 then  
  613.      raise e_invalid_stuno;  
  614.   else  
  615.     --insert into my_student values(2,'kate',49);--DUP_VAL_ON_INDEX异常  
  616.     select stuname, stuage into v_stuname,v_stuage  
  617.     from my_student  
  618.     where stuno=x_stuno;--加上or stuname like '%y'产生值记录太多异常  
  619.     dbms_output.put_line('sutdent name'||v_stuname||', student age:'||v_stuage);  
  620.   end if;  
  621.   exception  
  622.     when NO_DATA_FOUND then  
  623.       dbms_output.put_line('There is no student with stu no '||x_stuno);  
  624.     when VALUE_ERROR then  
  625.       dbms_output.put_line('值不匹配');  
  626.     when TOO_MANY_ROWS then  
  627.       dbms_output.put_line('记录太多');  
  628.     when e_invalid_stuno then       --控制台输入execute uuu_show_student(-2);  
  629.       dbms_output.put_line('学生编号不合法');  
  630.     when DUP_VAL_ON_INDEX then  
  631.       dbms_output.put_line('主键不可重复,插入失败');  
  632.     when OTHERS then   
  633.       dbms_output.put_line('其它异常捕获');--一些预定义异常的父类  
  634.           
  635. end uuu_show_student;  
  636.       
  637.   
  638. ==================================================================  
  639.   
  640. --触发器的一个例子  
  641. create or replace trigger student_aud  
  642.   before insert on my_student    
  643.   for each row  
  644. declare  
  645.   v_highage int;  
  646. begin  
  647.     
  648.   select stu_highage  
  649.   into v_highage  
  650.   from stu_stat;  
  651.     
  652.     
  653.   if :NEW.stuage >25 then  
  654.      v_highage:=v_highage+1;  
  655.   end if ;  
  656.     
  657.   update stu_stat set stu_count=stu_count+1,stu_highage=v_highage;  
  658.     
  659. end student_aud;