《Oracle PLSQ实例精解》笔记

使用替代变量接收用户输入

declare
  v_input_id number := &in_id; --使用&in_id接受用户输入
  v_name varchar2(35);
  v_id number;
  c_counter constant number := 0;
begin 
  dbms_output.put_line('begin');
  select id,name into v_id,v_name from t_user where id = v_input_id;
  dbms_output.put_line('id='||v_id||' name='||v_name); 
  dbms_output.put_line('end'); 
exception
  when no_data_found then 
      dbms_output.put_line('not find the student');
end;

使用anchored数据类型

declare
  v_name t_user.name%type; --v_name的数据类型基于表t_user的name字段,
                           --这使得如果以后该字段修改了类型,pl/sql无需修改
  v_id t_user.id%type;
  c_counter constant number := 0;
begin 
  dbms_output.put_line('begin');
  select id,name into v_id,v_name from t_user where id = 1;
  dbms_output.put_line('id='||v_id||' name='||v_name); 
  dbms_output.put_line('end'); 
exception
  when no_data_found then 
      dbms_output.put_line('not find the student');
end;

嵌套代码块的变量作用域

declare
  outer_counter number := 1;
begin 
  declare
    inner_count number := 2;
  begin
    dbms_output.put_line(outer_counter||' '||inner_count);
  end;
  --dbms_output.put_line(outer_counter||' '+inner_count); 无法访问到inner_count变量
end;

创建序列

    create sequence SEQ_STUDENT  --序列名
    increment BY 1              --每次加几个  
    start with 1                --从1开始计数  
    NOMAXVALUE                  --不设置最大值  
    NOCYCLE                     --一直累加,不循环  
    CACHE 20;                   --调用该序列器时生成20个以备下次取用,全用完时,下一次调用再生成20个

使用savePoint

declare
  outer_counter number := 1;
begin 
  insert into t_user values ('27',my_sequence.nextval);
  savepoint A;
  insert into t_user values ('28',my_sequence.nextval);
  savepoint B;
  insert into t_user values ('29',my_sequence.nextval);
  savepoint C;
  rollback to B;
  commit;
end;
--最后只有前两条记录会插入数据库

条件控制语句

IF语句

declare
  bigValue number := 5;
  smallValue number := 10;
  tempValue number;
begin 
  if  bigValue < smallValue then 
    dbms_output.put_line('bigValue 小于 smallValue');  
  else 
    dbms_output.put_line('bigValue 大于 smallValue');
  end if; 
  
  if bigValue = 3 then
    dbms_output.put_line('bigValue=3');  
  elsif bigValue = 4 then 
    dbms_output.put_line('bigValue=4'); 
  elsif bigValue = 5 then 
    dbms_output.put_line('bigValue=5');
  else  --else不是必须的
    dbms_output.put_line('bigValue is nothing');
  end if;          
       
  if bigValue < smallValue then
     tempValue := bigValue;
     bigValue := smallValue;
     smallValue := tempValue;
   end if;
   dbms_output.put_line('bigValue='||bigValue||' smallValue='||smallValue);  
end;

CASE语句

declare
  bigValue number := 5;
  smallValue number := 10;
  tempValue number;
  resultStr varchar2(30);
begin 
 -- 比较选择器的值和when运算器的值,true则执行
  case bigValue 
    when 3 then 
      dbms_output.put_line('bigValue=3');
    when 4 then 
      dbms_output.put_line('bigValue=4');
    when 5 then 
      dbms_output.put_line('bigValue=5');
    else dbms_output.put_line('bigValue is nothing');
  end case; 
  
  --搜索式case 1.无选择器  2.when子句产生boolean值
  case 
    when bigValue < smallValue then 
      dbms_output.put_line('bigValue 小于 smallValue');
    when bigValue is null then
      dbms_output.put_line('bigValue is null');  
    else 
      dbms_output.put_line('bigValue 不小于 smallValue'); 
  end case; 
  
  --case语句作为表达式返回
  resultStr := case 
                  when bigValue < smallValue then 
                    'bigValue 小于 smallValue' 
                  when bigValue is null then
                    'bigValue is null' 
                  else
                    'bigValue is nothing'   
                end;
  dbms_output.put_line(resultStr);               
end;
--将case嵌入到select语句中
declare
  v_id number := 11;
  v_name varchar2(30);
begin 
  select id,
  case 
    when id = 1 then '第一位'
  end       
  into v_id,v_name from t_user where id = 1;
  dbms_output.put_line(v_id||'  '||v_name);                          
end;

迭代控制语句

简单循环

DECLARE

BEGIN  
  loop --开启简单循环
    dbms_output.put_line(my_sequence.nextval);
    if my_sequence.nextval = 25 then 
      exit; --结束简单循环
    end if;
  end loop; 
END;

EXIT WHEN

BEGIN  
  loop
    dbms_output.put_line(my_sequence.nextval);
    exit when my_sequence.currval >= 50; --使用exit when 结束循环
  end loop; 
END;

WHILE

BEGIN  
  while my_sequence.currval <= 60 loop
    dbms_output.put_line(my_sequence.nextval);
  end loop;  
END;

数字FOR循环

begin
  for v_count in 1..5
    loop
      exit when v_count >= 3;
      dbms_output.put_line('v_count='||v_count);
    end loop;
end;    

CONTINUE

begin
  for v_count in 1..8
    loop
      continue when v_count = 3;
      if v_count = 5 then
        continue;
      end if;  
      dbms_output.put_line('v_count='||v_count);
    end loop;
end;    

错误和异常

declare
  v_count1 integer := 6;
  v_count2 integer := 0;
  v_count3 integer;  
begin
  v_count3 := v_count1/v_count2;
  dbms_output.put_line('v_count1/v_count2='||v_count3);
exception
  when zero_divide then
    dbms_output.put_line('0不能被除');
  when others then
    dbms_output.put_line('其他异常')
end;    

--自定义异常
declare
  e_my_exception exception;
  c_name  varchar2(10) := &name;
begin
  if c_name = '1' then 
    raise e_my_exception;
  else
    dbms_output.put_line('用户输入的值是:'||c_name);
  end if;  
exception
  when e_my_exception then
    dbms_output.put_line('自定义异常出现了!!!');
end;     

记录类型

记录是一种复合结构,它可以包含一个或多个元素。PL/SQL支持是三种记录:1.基于表的 2.基于游标的 3.程序员定义的

基于表和游标的记录

declare
  vr_row t_user%rowtype;
begin
  select * into vr_row from t_user where id = 2;
  dbms_output.put_line(vr_row.id||' == '||vr_row.name);
exception
  when no_data_found then
    dbms_output.put_line('error');
end;   

自定义的记录

type 类型名 is record
(
  字段名1 数据类型1,
  字段名2 数据类型2
    ...
)
记录名 类型名 %rowtype

游标

declare
  cursor c_user is select * from t_user;
  v_row t_user%rowtype; --记录类型
begin
  open c_user; --打开游标 
  loop
    fetch c_user into v_row ; --读取游标数据
    dbms_output.put_line(v_row.id||' == '||v_row.name);
     exit when c_user%notfound;
  end loop;  
exception
  when no_data_found then
    dbms_output.put_line('error');
end;   

游标属性

  1. %notfound 一个布尔属性。如果前一个fetch未返回一行,则返回false,否则返回true。
  2. %foun 一个布尔属性。如果前一个fetch返回至少一行,则返回true,否则返回false。
  3. %rowcount 在那个时刻,从一个游标读取到的记录数。
  4. %isopen 一个布尔属性。如果游标是打开的,则返回true,否则返回false。

游标For循环

declare
  cursor c_man is select * from t_user;
begin
  for man in c_man
    loop
      dbms_output.put_line(man.id||' '||man.name);
    end loop;
end;  

在游标中使用参数

declare
  cursor c_man(p_name in t_user.name%type) is select * from t_user where name = p_name;
begin
  for man in c_man('小2')
    loop
      dbms_output.put_line(man.id||' '||man.name);
    end loop;
end;      

函数

函数名 参数 描述
decode (expression,值1,翻译值1,值2,翻译值2,...值n,翻译值n,缺省值) 根据columnname的值翻译成其他的值
decode (expression,值1,值2,值3) 如果expression的值等于值,那就返回值2,否则返回值3
nvl (expression,值1) expression!=null?expression:值1
nullif (expression1,expression2) expression1expresion2 ? null : expression1
coalesce (expression1,expression2...expresionN) 依次计算每个表达式,返回第一个值不为null的值。如果所有值都为null,则返回null
trim (str) 去除字符串前后的空格
ltrim (str) 去除字符串前面的空格
rtrim (str) 去除字符串后面的空格

内置异常

异常 描述
zero_divide 0做除数异常
no_data_found 找不到数据异常
to_many_rows 当一个select into语句返回多行时,抛出异常
value_error 当转换或大小不匹配时抛出异常
dup_vlaue_on_index 当重复的数据被插入一个唯一索引列的抛出异常
invalid_number 当非字符型数据被赋值或更新到数据类型上
posted @ 2020-10-14 21:30  jwb1  阅读(95)  评论(0)    收藏  举报