PL/SQL程序结构及组成
- PL/SQL( Procedure Language/SQL)
- PL/SQL是Oracle对sql语言的过程化扩展
- 指在SQL命令语言中增加了过程处理语句(如分支,循环等),使SQL语言具有过程处理能力。
PL/SQL是Oracle对sql语言的过程化扩展,指在SQL命令语言中增加了过程处理语句(如分支,循环等),使SQL语言具有过程处理能力。把SQL语言的数据操纵能力与过程语言的数据处理能力结合起来,使得PLSQL面向过程但比过程语言简单,高效,灵活和实用。
PL/SQL是面向过程的语言,当然C也是。当下比较热门的大数据SCALA也是面向过程的语言。特别是对于用Java编程的人来说,学起来会轻松点,大部分都和Java语言差不多。Java=》hadoop,scala=》spark
PL/SQL工具实用
在新建窗口中,可选择如下。
Test window:使用存储过程。输出结果在DBMS OUTPUT
Sql window:数据库语句
F8执行
保存文件的时候,最好用sql结尾,因为这个样子可以用@的方式导入(在dos命令中)
PL/SQL入门
在dos命令中,PL/SQL是默认关闭,开启需如下SQL:
set serveroutput on
Declare:说明部分,后面跟变量的定义,如果没有变量得定义,可以不写。
Begin:开始
End:结束
程序包:相当于Java得API ,在Oracle中方法叫做存储过程或者存储函数。
查询API使用文档,在dos命令中输入如下:
Desc dbms_output
在存储过程中,输出语句如下:
dbms_output.put_line(’输出语句’);
程序语法
declare
说明部门(变量说明,游标申明,例外说明)
begin
语句序列(DML语句)...
exception
例外处理语句
end;
变量和常量说明
常见类型:char,varchar2,date,number,boolean,long。
说明变量名,数据类型和长度后用封号结束说明语句。如下:
varl char(15);
:=相当于= , =相当于==。如下:
married boolean :=true ;
数值,如下:
pasl number(7,2);
引用型变量,即my_name的类型与emp表中ename列的类型一样,如下:
my_name emp.ename%type
案例:
记录型变量,如下:
emp_rec emp%rowtype;
案例:
常量定义,如下:
vars constant char(15);
分支
IF语句
IF 条件 THEN 语句1;
语句2;
END IF;
IF 条件 THEN 语句序列1;
ELSE 语句序列2;
END IF;
IF 条件 THEN 语句;
ELSIF 条件 THEN 语句;
ELSE 语句;
END IF
键盘输入流
循环
WHILE total<=25000
LOOP
...
total := total+salary;
END LOOP;
LOOP
EXIT[WHEN 条件];
...
END LOOP;
FOR I IN 1...3
LOOP
语句序列;
END LOOP;
案例:
-- 打印1到10
declare
pnum number :=1;
begin
loop
--循环
--退出条件
exit when pnum > 10;
dbms_output.put_line(pnum);
--加一
pnum :=pnum + 1;
end loop;
end;
光标或游标(集合)
光标相当于集合,用来接受多行参数。
语法:
cursor c1 is select * from emp;--cursor 游标名 [(参数名 数i据类型,参数名 数据类型,...)] is select 语句;
游标的使用步骤:
- 打开游标: open c1;(打开游戏执行查询)
- 取一行游标的值:fetch c1 into pjob;(取一行到变量中)
- 关闭游标: close c1;(关闭游标释放资源)
- 游标的结束方式 exit when c1%notfound
- 注意:上面的pjob必须与emp表中的job列类型一致:
定义:pjob emp.empjob%type;
光标在集合中,第一个值是指着有值的地方。
而序列中的第一个指针是指着 没有值的地方。
案例:
/*
光标的属性:
%isopen %rowcount(影响的行数) %found %notfound
*/
declare
-- 定义光标
cursor cemp is select ename,sal from emp;
pename emp.ename%type;
psal emp.sal%type;
begin
-- 打开光标
open cemp;
loop
--取当前记录
fetch cemp into pename,psal;
--exit when 没有取到记录;
exit when cemp%notfound;
dbms_output.put_line(pename||'的薪水是'||psal);
end loop;
--关闭光标
close cemp;
end;
-- 涨工资,总裁1000 经理800 其他400
declare
-- 定义光标
cursor cemp is select empno,job from emp;
pempno emp.empno%type;
pjob emp.job%type;
begin
rollback;
--打开光标
open cemp;
loop
--取一个员工
fetch cemp into pempno,pjob;
exit when cemp%notfound;
--判断职位
if pjob = 'PRESIDENT' then update emp set sal=sal+1000 where empno=pempno;
elsif pjob = 'MANAGER' then update emp set sal=sal+800 where empno=pempno;
else update emp set sal=sal+400 where empno=pempno;
end if;
end loop;
--关闭光标
close cemp;
--提交 ---> ACID
commit;
dbms_output.put_line('完成');
end;
-- 查询某个部门的员工姓名
declare
cursor cemp(dno number) is select ename from emp where deptno=dno;
pename emp.ename%type;
begin
open cemp(20);
loop
fetch cemp into pename;
exit when cemp%notfound;
dbms_output.put_line(pename);
end loop;
close cemp;
end;
异常
语句 | 描述 |
NO_DATA_FOUND | 没有找到数据 |
Too_many_rows | select ...into语句匹配多个行 |
Zero_Divide | 被零除 |
Value_error | 算术或转换错误 |
Timeout_on_resource | 在等资源时发生超时 |
-- 被0除
declare
pnum number;
begin
pnum := 1/0;
exception
when zero_divide then dbms_output.put_line('1:0不能做分母');
dbms_output.put_line('2:0不能做分母');
when value_error then dbms_output.put_line('算术或者转换错误');
when others then dbms_output.put_line('其他例外');
end;
-- 查询50号部门的员工姓名
declare
--定义光标:代表50号部门的员工
cursor cemp is select ename from emp where deptno=50;
pename emp.ename%type;
--自定义例外
no_emp_found exception;
begin
open cemp;
--取第一条记录
fetch cemp into pename;
if cemp%notfound then
--抛出例外
raise no_emp_found;
end if;
--pmon进程: process monitor
close cemp;
exception
when no_emp_found then dbms_output.put_line('没有找到员工');
when others then dbms_output.put_line('其他例外');
end;