1、基础语法

http://692088846.iteye.com/blog/2017137   (%type、%rowtype、if\if else\if elseif else、while、do..while、游标、异常、函数、过程)

1.1 声明变量赋值并输出

 set serveroutput on --设置数据库输出,默认为关闭,每次重新打开窗口需要重新设置。
    Declare
       result integer;  --声明变量【变量名 变量类型】
    begin
       result:=10+3*4-20+5**2;  --给变量赋值【:=】
       dbms_output.put_line('运算结果是:'||to_char(result));
    end;
 --------------------------------------------------------------------------------------------------
    dbms_output.put_line函数输出只能是字符串,因此利用to_char函数将数值型结果转换为字符型。
    运算的优先次序为NOT、AND和OR。
    To_char:将其他类型数据转换为字符型。
    To_date:将其他类型数据转换为日期型。
    To_number:将其他类型数据转换为数值型。

1.2 %type、%rowtype、select...into

        -- %type 变量的类型和数据表中的字段的数据类型一致
        -- %rowtype  变量的类型和数据表中的一行记录数据类型一致
        --  select ... into 变量     表中查询数据并赋值,可以一次性给多个变量赋值
    declare 
      v_object CUSTOMER%Rowtype; 
    begin
      select * into v_object from customer where rownum=1;
      dbms_output.put_line(v_object.Enterprise_Code ||','||v_object.CreateDate);
    end;

1.3 只可以增删改  

     -- insert,update,delete,select都可以,create table,drop table不行。DPL,DML,和流程控制语句可以在pl/sql里用但DDL语句不行,表定义语言不可以在plsql中改变
    
    declare
       v_name student.name%type:='wang'; --声明变量并赋值
    begin
       insert into student(id,name,age) values(2,v_name,26);  --插入数据
    end;
  --------------------------------------------
    declare
       v_name student.name%type:='hexian';              --更新数据
    begin
       update student set name=v_name where id=1;
    end;
    begin
       update student set name='qinaide' where id=2;
    end;
  ------------------------------------------------- --------------

2、 PLSQL流程控制

 --if判断---

        declare
             v_b boolean:=true;   -- := 是赋值
        begin 
                 if v_b then
                      dbms_output.put_line('ok');
                end if;
        end;

 --if else判断---

        declare
             v_b boolean:=true;
        begin
             if v_b then
                  dbms_output.put_line('ok');
             else
                  dbms_output.put_line('false');
             end if;
        end;

--if elsif else判断--

        declare
                v_name varchar2(20):='cheng';
        begin
                 if v_name='0701' then
                        dbms_output.put_line('0701');
                 elsif v_name='cheng' then
                        dbms_output.put_line('cheng');
                 else
                        dbms_output.put_line('false');
                 end if;
        end;

 --loop循环,注意推出exit是退出循环,而不是推出整个代码块

        declare
                v_i binary_integer :=0;
        begin
                 loop
                     exit when v_i>10;
                         v_i :=v_i+1;
                         dbms_output.put_line('hehe');
                 end loop;
                         dbms_output.put_line('over');
        end;

 -- while循环

        declare
                     v_i binary_integer:=0;
        begin
                     while v_i<10 loop
                                 dbms_output.put_line('hello'||v_i );
                                 v_i:=v_i+1;
                     end loop;
                     dbms_output.put_line('over');
        end;

-- for循环,注意不需要声明变量

        begin
                 for v_i in 0..10 loop
                         dbms_output.put_line('hello'||v_i);
                 end loop;
                         dbms_output.put_line('over');
        end;                       

3、PLSQL异常处理

        1、声明异常
         异常名 EXCEPTION;
        2、抛出异常
         RAISE 异常名
        3、处理异常
         抛出异常后的逻辑代码不会被继续执行
        异常的定义使用
 ―――――――――――――――――――――――――――――――――――――
    begin
          dbms_output.put_line(1/0);  --1/0出现错误,抛出异常,输出error
    exception
          when others then
             dbms_output.put_line('error');
    end;
 -----------------------------------------------------------------------------
    declare
            e_myException exception; --声明异常
    begin
            dbms_output.put_line('hello');
                        --raise抛出异常,用此关键字,抛出后转到自定义的e_myException,执行其
                        --里面的putline函数后,再跳到end处,结束PL/SQL块,raise接下面的2句不会继续执行。
            raise e_myException; 
            dbms_output.put_line('world');
            dbms_output.put_line(1/0);
    exception
            when e_myException then   --执行异常
                dbms_output.put_line(sqlcode); --当前会话执行状态,错误编码
                dbms_output.put_line(sqlerrm); --当前错误信息
                dbms_output.put_line('my error');
            when others then
                dbms_output.put_line('error');
    end;     
 

4、 PLSQL游标

4.1 游标定义

        备注:把游标看作一个集合
        游标,从declare、open、fetch、close是一个完整的生命旅程。cursor 游标(结果集)用于提取多行数据,定义后不会有数据,使用后才有。一旦游标被打开,就无法再次打开(可以先关闭,再打开)。          
--游标的定义
declare
    v_title books.title%type; --声明为和数据库中数据相同的类型
    v_retail books.retail%type;
    cursor book_cursor is  --把游标看作一个集合
        select title, retail form books natural join orderitems where order=1012;
Begin
    open book_cursor  --打开游标
    loop 
        fetch books_cursor into v_title, v_ratial; --通过循坏提取数据
        exit when book_cursor%notfound   --如果没有数据就退出循坏
        dbms_output.line('book title:' || v_title || ',price:' || v_retail);
    end loop;
  close book_cursor;  --关闭游标
end;
    
        
--第二种游标的定义方式,用变量控制结果集的数量。
    declare
        v_id  binary_integer;
        cursor c_student is select * from book where id > v_id;      
    begin
        v_id:=10;
        open c_student;
        close c_student;
    end;
--第三种游标的定义方式,带参数的游标,用的最多。
    declare
        cursor c_student(v_id binary_integer) is select * from book where id>v_id;
    begin
        open c_student(10);
        close c_student;
    end; 
View Code

4.2 游标的使用

        游标的使用,一定别忘了关游标。
                declare
                     v_student book%rowtype;
                     cursor c_student(v_id binary_integer) is select * from book where id>v_id;
                begin
                     open c_student(10);
                     fetch c_student into v_student;
                     close c_student;
                     dbms_output.put_line(v_student.name);
                end;
 
        如何遍历游标fetch
            游标的属性 %found,%notfound,%isopen,%rowcount。
            %found:若前面的fetch语句返回一行数据,则%found返回true,如果对未打开的游标使用则报ORA-1001异常。
            %notfound,与%found行为相反。
            %isopen,判断游标是否打开。
            %rowcount:当前游标的指针位移量,到目前位置游标所检索的数据行的个数,若未打开就引用,返回ORA-1001。
        注:
        no_data_found和%notfound的用法是有区别的,小结如下
        1)SELECT . . . INTO 语句触发 no_data_found;
        2)当一个显式光标(静态和动态)的 where 子句未找到时触发 %notfound;
        3)当UPDATE或DELETE 语句的where 子句未找到时触发 sql%notfound;
        4)在光标的提取(Fetch)循环中要用 %notfound 或%found 来确定循环的退出条件,不要用no_data_found。

4.3 游标实例:

1、loop方式遍历游标

    declare
          v_bookname  varchar2(100);
                    --带参数的游标,把游标当做一个集合(只有bookname的集合)
          cursor c_book(i_id number) is select bookname from book where id = i_id; 
    begin
        Open  c_book(i_id); --打开游标
        Loop
            Fetch c_book into v_bookname;  --获取数据
            exit when c_student%notfound;   
              update book set price = '33' where bookname = v_bookname; --如果该id对应的bookname没值则更新
        End Loop;
        Close c_book;  --关闭游标
    end;
    或
    declare
          v_bookname  varchar2(100);
          cursor c_book(i_id number) is select bookname from book where id = i_id;
    begin
        Open  c_book(i_id);
          Fetch c_book into v_bookname; 
          While c_book%Found
          Loop
              update book set price = '33' where bookname = v_bookname;
              Fetch  c_book into v_bookname;
          End Loop;
        Close c_book;
    end;  
2、while循环遍历游标,注意,第一次游标刚打开就fetch,%found为null,进不去循环

解决方法:while nvl(c_student%found,true) loop
    declare
         v_bookname  varchar2(100);
         cursor c_book(i_id number) is select bookname from book where id = i_id;
    begin
         Open  c_book(i_id);
         while nvl(c_book%found,true) --或这种写法:while c_book%found is null or c_book%found loop    
             Fetch c_book into v_bookname;
             update book set price = '33' where bookname = v_bookname;
         End Loop;
         Close c_book;
    end;
3、 for循环遍历

  - 最简单,用的最多,不需要 声明v_student,Open和Close游标和fetch操作(不用打开游标和关闭游标,实现遍历游标最高效方式)
    declare
         cursor c_book(i_id number) is select bookname from book where id = i_id;
    begin
         for cur in c_book(i_id) --直接将入参i_id传入cursor即可
         loop
             update book set price = '53' where bookname = cur.bookname;
         end loop;
    end;
遍历游标

相关文章:

  • 2021-08-13
  • 2022-12-23
  • 2021-09-26
  • 2021-11-05
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-01-15
猜你喜欢
  • 2022-12-23
  • 2021-04-29
  • 2022-12-23
  • 2022-12-23
  • 2021-12-28
  • 2022-12-23
  • 2021-06-01
相关资源
相似解决方案