新公司数据库用的是Oracle数据库,之前用的都是Msql。于是赶紧找了本《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;
游标属性
- %notfound 一个布尔属性。如果前一个fetch未返回一行,则返回false,否则返回true。
- %foun 一个布尔属性。如果前一个fetch返回至少一行,则返回true,否则返回false。
- %rowcount 在那个时刻,从一个游标读取到的记录数。
- %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 |
当非字符型数据被赋值或更新到数据类型上 |