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;
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;