• Procedure-Function oracle


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

    0.调试

        点击procedure名,右键选择调试。即可进入调试模式。找到procedure,点击右键,查看,可看到编译错误信息。

        Dbms_output.Put_line('打印内容:' || v_total); --打印

      v_str:=&dno; 其中 &表示键盘输入。即接收键盘输入的值dno表示Name。

    1.基本用法

      查看所有的存储过程:

      select object_name,object_type,status from user_objects where OBJECT_TYPE='PROCEDURE';

      查看某个存储过程:

      SELECT text FROM user_source WHERE NAME = 'procedure_name';

      删除:

      drop procedure procedure_name;

      新增:

      create or replace procedure procedure_name;

    CREATE OR REPLACE PROCEDURE test1 IS
    v_total NUMBER;
    BEGIN
    SELECT COUNT(*) INTO v_total FROM user;
    Dbms_output.Put_line(v_total);  --打印

    END;

     1 存储过程创建语法:
     2 
     3create or replace procedure procedure_name(param1 in type,param2 out type,param3 in out type) --参数类型不需要定义值范围
     4 
     5 as
     6 
     7 变量1 类型(值范围);
     8 
     9 变量2 类型(值范围);
    10 
    11 Begin
    12 ...........
    13 END [procedure_name];
    1 begin
    2 execute immediate 'ALTER TABLE RECORD_XWZX5_left ADD (ID NUMBER)';
    3 execute immediate 'ALTER TABLE RECORD_XWZX5_right ADD (ID NUMBER)';
    4 update RECORD_XWZX5_right set ID = ROWNUM;
    5 update RECORD_XWZX5_left set ID = ROWNUM;
    6 commit;
    7 end ;
    8 
    9 执行多条插入语句

          1.  其中的 IS 可以用 AS来替代,两个是同义词。(oracle数据库表名不能用as)

        在视图(VIEW)中只能用AS不能用IS

        在游标(CURSOR)中只能用IS不能用AS

           2.     Select 必须有 INTO 接收值的变量(select ** into v_name ),不然报错,在赋值时最好用count(*)测试下,是否有多值和无值的情况发生,在Exception中处理结果。

    调用:

    // pLsql调用
    BEGIN
    test1(); END;

    // 外部程序调用
    [EXECUTE]|[CALL] procedure_name[(parameter,…n)]

    2. 变量

    DECLARE v1 hr_user.oa_name%TYPE;

      赋值:

    v1:='zhangsan';

    v_count INT :=30;

    声明时不能够赋值,只能default形式设定默认值。

    3.参数

       存储过程的参数不用带取值范围直接定义类型即可,且形式只有IN和OUT两种,或者将两个都共存。

       CREATE OR REPLACE PROCEDURE test1(v1 in varchar, v2 out varchar,v3 in out varchar) 默认为IN形式。

     1 /* 创建 */
     2 CREATE OR REPLACE PROCEDURE test1(v1 VARCHAR, v2 OUT INT) IS
     3 BEGIN
     4   SELECT COUNT(*) INTO v2 FROM user WHERE name = v1;
     5   Dbms_output.Put_line(v2);
     6 EXCEPTION
     7   WHEN NO_DATA_FOUND THEN
     8     v2 := 0;
     9     Dbms_output.Put_line(v2);
    10   WHEN OTHERS THEN
    11     ROLLBACK;
    12 END;
    13 
    14 
    15 /* 调用 */
    16 DECLARE v1 VARCHAR(100);
    17 v2 INT;
    18 BEGIN
    19   v1:='zhangsan';
    20 test1(v1, v2);
    21 END;

         另一种声明变量参数的方式%type。

       %type 表示将参数的类型和表中的某个字段绑定,使用字段定义的参数类型。这样当参数类型变化时,存储过程中的跟着变化。

        CREATE OR REPLACE PROCEDURE test1(v1 user.name%TYPE, v2 OUT INT) IS

    PROCEDURE APPS.TEST1 编译错误 错误:PLS-00363: 表达式 'V_INCREMENT' 不能用作赋值目标 In out 被作为了常量,因此不能够被赋值,只能获取。

    默认传参:

    默认存储过程传参是按照前后顺序进行,

    test1(va,vb);

    如果不按照前后顺序,则使用以下方式:

    1 DECLARE 
    2 va hr_user.oa_name%TYPE;
    3 ve INT;
    4 BEGIN
    5   va:='zhangsan';
    6 test1(v1 =>va, v2 =>ve);
    7 END;

    4.raise ***主动抛出异常

     1 CREATE OR REPLACE PROCEDURE test1(v1 VARCHAR, v2 OUT INT) IS
     2 BEGIN
     3   SELECT COUNT(*) INTO v2 FROM user WHERE name = v1;
     4   Dbms_output.Put_line(v2);
     5   IF v2 > 1 THEN
     6     RAISE TOO_MANY_ROWS;
     7   ELSIF v2 = 0 THEN
     8     RAISE NO_DATA_FOUND;
     9   END IF;
    10 EXCEPTION
    11   WHEN NO_DATA_FOUND THEN
    12     v2 := 0;
    13     Dbms_output.Put_line('未查询到任何数据');
    14   WHEN TOO_MANY_ROWS THEN
    15     Dbms_output.Put_line('返回多行数据');
    16   WHEN OTHERS THEN
    17     ROLLBACK;
    18 END;

    命名的系统异常                          产生原因

    ACCESS_INTO_NULL                   未定义对象

    CASE_NOT_FOUND                     CASE 中若未包含相应的 WHEN ,并且没有设置

    ELSE 时

    COLLECTION_IS_NULL                集合元素未初始化

    CURSER_ALREADY_OPEN          游标已经打开

    DUP_VAL_ON_INDEX                   唯一索引对应的列上有重复的值

    INVALID_CURSOR                 在不合法的游标上进行操作

    INVALID_NUMBER                       内嵌的 SQL 语句不能将字符转换为数字

    NO_DATA_FOUND                        使用 select into 未返回行,或应用索引表未初始化的  

    TOO_MANY_ROWS                      执行 select into 时,结果集超过一行

    ZERO_DIVIDE                              除数为 0

    SUBSCRIPT_BEYOND_COUNT     元素下标超过嵌套表或 VARRAY 的最大值

    SUBSCRIPT_OUTSIDE_LIMIT       使用嵌套表或 VARRAY 时,将下标指定为负数

    VALUE_ERROR                             赋值时,变量长度不足以容纳实际数据

    LOGIN_DENIED                           PL/SQL 应用程序连接到 oracle 数据库时,提供了不

    正确的用户名或密码

    NOT_LOGGED_ON                       PL/SQL 应用程序在没有连接 oralce 数据库的情况下

    访问数据

    PROGRAM_ERROR                       PL/SQL 内部问题,可能需要重装数据字典& pl./SQL

    系统包

    ROWTYPE_MISMATCH                宿主游标变量与 PL/SQL 游标变量的返回类型不兼容

    SELF_IS_NULL                             使用对象类型时,在 null 对象上调用对象方法

    STORAGE_ERROR                        运行 PL/SQL 时,超出内存空间

    SYS_INVALID_ID                         无效的 ROWID 字符串

    TIMEOUT_ON_RESOURCE         Oracle 在等待资源时超时  

    6. 流程结构控制

       IF: if 条件 then

       else

       end if

    ----------------------

      if 条件 then

    elsif 条件 then

    end if

    这里中间是“ELSIF”,而不是ELSE IF 。这里需要特别注意

      WHILE:

    WHILE ... LOOP

        [BEGIN]

        [END];

    END LOOP;

     1 CREATE OR REPLACE PROCEDURE TEST1(v_increment IN INT) IS
     2   v_count INT := 30;
     3   v_icre  INT DEFAULT v_increment;
     4 BEGIN
     5   WHILE v_icre < v_count LOOP
     6     BEGIN  --可加可不加
     7       Dbms_output.Put_line('打印内容:' || v_icre);
     8       v_icre := v_icre + 1;
     9     END;
    10   END LOOP;
    11 END TEST1;

    7. 游标cursor使用

      cursor 只能用IS修饰。

    注意:因为游标的效率较差,如果游标操作的数据超过1万行,那么就应该改写;游标类型:隐式游标和显式游标。
          隐式游标:DML(数据操作语言包括:INSERT,DELETE,UPDATE,SELECT... INTO 等单行语句) SQL语句都会使用隐式游标调用。
    属性 返回值类型 说明
    SQL%ROWCOUNT 整型 代表DML语句成功执行的数据行数
    SQL%FOUND 布尔型 TRUE代表插入、删除、更新或单行查询操作成功
    SQL%NOTFOUND 布尔型 与SQL%FOUND属性返回值相反
    SQL%ISOPEN 布尔型 DML执行过程中为真,结束后为假

     

              显式游标:DQL(查询语句select) sql返回多行数据时,使用显式游标调用。

        %Found :Fetch语句(获取记录)执行情况True or False。
        %NotFound : 最后一条记录是否提取出True or False。
        %ISOpen : 游标是否打开True or False。
        %RowCount :游标当前提取的行数 。

    定义:   CURSOR cur IS SELECT * FROM user;

    传参:   v_cur cur%rowType;一行数据类型

     FOR循环游标隐式打开游标,自动滚动获取一条记录,并自动创建临时记录类型变量存储记录。处理完后自动关闭游标。
    fetch ... into ... 游标开始在空行,使用fetch into 使得游标进入下一行
    注意: 只是要注意用更新游标的时候,不能在游标期间commit. 否则会报
    ORA-01002: fetch out of sequence
          就是COMMIT;导致错误
           在打开有for update的cursor时,系统会给取出的数据加上排他锁(exclusive),
           这样在这个锁释放前其他用户不能对这些记录作update、delete和加锁。
           而我一旦执行了commit,锁就释放了,游标也变成无效的,再去fetch数据时就出现错误了。
           因而要把commit放在循环外,等到所有数据处理完成后再commit,然后关闭cursor

       使用(for ... in  ... loop .... end loop直接开始游标): 

         for  cur_result in cur loop

          v_name:=cur_result.column_name;

        end loop;

     1 CREATE OR REPLACE PROCEDURE TEST1(v_increment IN INT) IS
     2   v_name VARCHAR(100);
     3   v_type VARCHAR(100);
     4   CURSOR cur IS
     5     SELECT * FROM user WHERE rownum < 50;
     6 BEGIN
     7   FOR cur_result IN cur LOOP
     8     v_name := cur_result.name;
     9     v_type := cur_result.type;
    10     Dbms_output.Put_line('打印内容:' || v_name || '   ' || v_type);
    11   END LOOP;
    12 END TEST1;

    使用2(loop fetch cur into ...): 

     1 CREATE OR REPLACE PROCEDURE TEST1(v_increment IN INT) IS
     2   v_name VARCHAR(100);
     3   v_type VARCHAR(100);
     4   CURSOR cur IS
     5     SELECT name, type FROM user WHERE rownum < 50;
     6 BEGIN
     7   OPEN cur;
     8   LOOP
     9     FETCH cur
    10       INTO v_name, v_type;
    11     EXIT WHEN cur%NOTFOUND;
    12     BEGIN
    13       Dbms_output.Put_line('打印内容:' || v_name || '   ' || v_type);
    14     END;
    15   END LOOP;
    16   CLOSE cur;
    17 END TEST1;

    使用3(while):

     1 CREATE OR REPLACE PROCEDURE TEST1(v_increment IN INT) IS
     2   v_name VARCHAR(100);
     3   v_type VARCHAR(100);
     4   CURSOR cur IS
     5     SELECT name, type FROM user WHERE rownum < 50;
     6   v_row cur%ROWTYPE;  --变量定义必须在begin之前
     7 BEGIN
     8   OPEN cur;
     9   FETCH cur INTO v_row; --fetch将值赋予v_row
    10   WHILE cur%FOUND LOOP
    11     Dbms_output.Put_line('打印内容:' || v_row.name || '   ' ||
    12                          v_row.type);
    13     FETCH cur INTO v_row;
    14   END LOOP;
    15   CLOSE cur;
    16 END TEST1;

    4.游标带参

     1 CREATE OR REPLACE PROCEDURE TEST1(v_oname IN VARCHAR) IS
     2   v_name VARCHAR(100);
     3   v_type VARCHAR(100);
     4   CURSOR cur(v_name1 VARCHAR) IS
     5     SELECT name, type FROM user
     6      WHERE name = v_name1
     7        AND rownum < 50;
     8   v_row cur%ROWTYPE;
     9 BEGIN
    10   OPEN cur(v_oname);
    11   FETCH cur
    12     INTO v_row;
    13   WHILE cur%FOUND LOOP
    14     Dbms_output.Put_line('打印内容:' || v_row.name || '   ' ||
    15                          v_row.type);
    16     FETCH cur
    17       INTO v_row;
    18   END LOOP;
    19   CLOSE cur;
    20 END TEST1;

    5. 游标更新和删除

    CURSOR cursor_name IS select_statement  
    FOR UPDATE [OF column_reference] [NOWAITE];   -- OF子句指定对特定表加锁。  
    UPDATE table_name SET column=.. WHERE CURRENT OF cursor_name;  
    DELETE table_name WHERE CURRENT OF cursor_name; 

    6.批量提取

      FETCH ... BULK COLLECT INTO ...[LIMIT row_number];

     1 CREATE OR REPLACE PROCEDURE TEST1(v_oname IN VARCHAR) IS
     2   v_name VARCHAR(100);
     3   v_type VARCHAR(100);
     4   CURSOR cur IS
     5     SELECT *
     6       FROM user
     7      WHERE name LIKE '%' || v_oname || '%'
     8        AND rownum < 50;
     9   v_row cur%ROWTYPE;
    10 
    11   TYPE type_user IS TABLE OF user%ROWTYPE INDEX BY BINARY_INTEGER;
    12   user_table type_user;
    13 BEGIN
    14   OPEN cur;
    15   FETCH cur BULK COLLECT
    16     INTO user_table limit 5;
    17   CLOSE cur;
    18   FOR i IN 1 .. user_table.count LOOP
    19     Dbms_output.Put_line('打印内容:' || user_table(i).name || '   ' || user_table(i) .type);
    20   END LOOP;
    21 END TEST1;

    参考:

    Oracle存储过程创建及调用(http://www.cnblogs.com/chinafine/articles/1776094.html)

    Oracle存储过程学习(http://www.cnblogs.com/chuncn/archive/2009/01/29/1381291.html)

    Oracle游标使用全解(http://blog.csdn.net/jeathenzhang/article/details/8853607)

    plsql游标详解(http://blog.csdn.net/kb5706/article/details/7575445)

  • 相关阅读:
    js去掉字符串前后空格三种方法及最佳方案
    javascript笔记:Date对象及操作方法
    高性能网站建设指南总结
    javascript之词法作用域及函数的运行过程
    LETTers比赛第四场N!
    LETTers比赛第三场 1003 大明A+B解题报告
    LETTers比赛第三场 1004 Max Sum Plus Plus 解题报告
    LETTers比赛第三场 1002 Ignatius and the Princess III解题报告
    LETTers第五场Sleeping 解题报告
    LETTers比赛第四场N!的最高位
  • 原文地址:https://www.cnblogs.com/DennyZhao/p/7081884.html
Copyright © 2020-2023  润新知