一、PLSQL基础
1、PL/SQL 简介
2、标识符
3、数据类型
4、变量和常量
二、流程控制语句
1、条件控制
IF语句
case语句
2、循环控制
(1) loop 循环
(2)while 循环
(3)for 循环
3、顺序控制
GOTO 语句
NULL 语句
三、游标
1、游标简介
2.游标类型
3.游标属性
4、显式游标
5、隐式游标
6、ref 游标
四、集合
1、集合类型
2.集合的属性和方法
4、嵌套表
5、变长数组
6、bulk collect
7、批量绑定
一、PLSQL基础
1、PL/SQL 简介
编程语言 。
declare (声明部分) begin (plsql代码块) end;
输出 语句:drop_output.put_lline()
拼接:||
2、标识符
下划线由字母、数字、(_)和(#)组成,从字母开始。
3、数据类型
(1)数值类型
number
pls_integer,binary_integer:数值类型只能用来存储整数
(2)字符串类型
&nbp; varchar2(长度):变长字符串类型
char(len):定长字符串类型
(3)日期类型
date:日期类型
(4)record 类型
可以用来存放一组值,使用之前需要去定义一个确定的记录类型
怎么定义?
type 名字 is record(
变量名 数据类型,
变量名 数据类型
);
比如:
type re is record(
name varchar2(10),
sex number(5),
age number(10)
);
声明一个记录类型变量:
v_re re;
给记录类型赋值:
v_re.name='张三';
(5)%type 类型
是取数据库表中某一个字段的类型来作为变量类型
写法 如:emp.ename%type 等同于 varchar2(10);
(6)%rowtype类型
它是%type类型和record类型的结合
写法 如:v_dept dept%rowtype;
v_dept变量里面含有dept表里面的所有字段类型,使用的时候直接v_dept.deptno 就可以了。
4、变量和常量
pl/sql 里面赋值是符号
变量:如: v_n number(10) := 1 ;
常量:如: PI constant number := 3.14 ;
如:select deptno into v_deptno from dept where deptno=&deptno;
二、流程控制语句
1、条件控制
IF 语句
(1) if 条件表达式 then
plsql语句;
end if;
if 条件表达式 then
plsql语句;
end if;
........
(2) if 条件表达式 then
plsql语句;
else
plsql语句;
end if;
(3) if 条件表达式 then
plsql语句;
elsif 条件表达式 then
........
else
plsql语句;
end if;
case 语句
(1) case
when 条件表达式1 then
plsql语句;
when 条件表达式 2 then
plsql语句;
........
end case;
(2) case 条件表达式
when 值1 then
plsql语句;
when 值2 then
plsql语句;
.......
end case;
2、循环控制
(1) loop 循环
语法:loop
plsql语句;
exit when 退出循环的条件;
循环控制语句;
end loop;
(2)while 循环
语法:while 循环条件 loop
循环体语句;
循环控制语句;
end loop;
(3)for 循环
for 循环变量 in 集合 | 查询语句 | 游标变量 loop
循环体语句;
end loop;
3、顺序控制
GOTO 语句
语法:
<<lable>>
循环执行的plsql语句;
if 条件 then
goto lable;
end if;
其中<<>> 是标签定义符。
--循环打印 1 到 9
declare
n number(10):=1;
begin
<<mylable>>
dbms_output.put_line(n);--(1)
n:=n+1;--(2)
if n < 10 then
goto mylable;--相当于原先在此处的(1),(2)放到标签那里
end if;
end;
NULL 语句
plsql 中的空语句,什么也不做,就是占个位置。
三、游标
1、游标简介
cursor : 逐行处理查询结果,实际上是一个指针,指向一个结果集。
2、游标的类型
(1)隐式游标 :执行 pl/sql 里的DML (insert, delete,update, select)语句时,会自动创建隐式游标,名字固定叫 sql 。
(2)显式游标:用于处理返回多行的查询。
(3)ref 游标:用于处理运行时才能确定的查询结果,可以重复使用。
3、游标的属性
(1)%found :返回值为布尔值, 如果游标指向的数据有值,(可以found)返回true,否则返回false。
(2)%notfound :和上面相反,找不到为true(也就是空了),否则false。
(3)
(4)%isopen :返回值为布尔值,判断当前游标是否打开,打开就是true,否则就是false。
4、显式游标
其实就是自己定义的游标。查询结果为多行的数据都可以用游标来接。
如何使用?
(1)声明: cursor 游标名 is select 语句;
如:cursor c_emp is select * from emp;
(2)打开游标:open 游标名称;
如:open c_cursor;
(3)fetch into 使当前游标指向下一条数据。
fetch 游标变量 into 变量; (fetch: 从...中取)
如:fetch c_emp into v_emp;
(4)关闭游标:close 游标名称;
如:close c_emp;
例:使用游标打印所有员工的信息
--for 循环写
declare
cursor c_emp is select * from emp;
begin
for v_emp in c_emp loop
dbms_output.put_line(v_emp.empno||','||v_emp.ename||','||v_emp.deptno);
end;
--loop 循环写
declare
cursor c_emp is select * from emp;
v_emp emp%rowtype;
begin
open c_emp;
fetch c_emp into v_emp;
loop
dbms_output.put_line(v_emp.empno||','||v_emp.ename||','||v_emp.deptno);
exit when c_emp%notfound;
fetch c_emp into v_emp;
end;
--while 循环写
declare
cursor c_emp is select * from emp;
v_emp emp%rowtype;
begin
open c_emp;
fetch c_emp into v_emp;
while c_emp%found loop
dbms_output.put_line(v_emp.empno||','||v_emp.ename||','||v_emp.deptno);
fetch c_emp into v_emp;
end loop;
dbms_output.put_line('共'||c_emp%rowcount||'条');
end;
while 循环执行的结果:
可以看一下三个循环写游标之间的区别,for循环最简单。
如:
declare
cursor c_emp(dno number) is select * from emp where deptno=dno;
begin
for i in c(&dno) loop
dbms_output.put_line(i.ename);
dbms_output.put_line(c%rowcount);
end loop;
end;
结果为:
:允许使用游标更新或删除结果集中的行。
declare cursor c_emp is select * from emp where deptno=10 for update; --后面加上 for update begin for v_emp in c_emp loop update emp set sal = sal+200 where current of c_emp; --where current of 游标名 表示对所在行进行更新和删除。 end loop; end;
5、隐式游标
使用DML语句的时候自动创建,名字固定为sql,使用和显示游标没有区别。
declare
v_emp emp%rowtype;
begin
update emp set comm=100 where deptno=&deptno;
dbms_output.put_line('修改的数据条数:'||sql%rowcount);
if sql%found then
dbms_output.put_line('aaaaaaaaaaaaaaa');
end if;
delete from emp where deptno=&dno;
dbms_output.put_line('删除了'||sql%rowcount||'条数据');
end;
输入的第一个部门是10,要删的部门输的是20
6、ref 游标
写个例子大家看一下就懂了。
--查询所有员工的信息
declare
type c_type is ref cursor; --声明一个ref 游标类型
cur c_type; ---声明一个ref 游标类型的变量
v_emp emp%rowtype;
begin
open cur for select * from emp; --open的时候指定cur 指向的结果集到底是什么
loop
fetch cur into v_emp;
exit when cur%notfound;
dbms_output.put_line(v_emp.ename);
end loop;
close cur;
end;
-----好像不能使用for循环,会报出一个cur不是过程或尚未被定义出现在for v_emp in cur loop这一行
四、集合
1、集合类型
集合:是存放一组相同数据类型的数据。
分为三种:(1)索引表:又叫关联数组。
(2)嵌套表
(3)可变长度数组
2、集合的属性和方法
(1)first:集合的第一个元素的下标
(2)last:集合的最后一个元素的下标
(3)count:集合的总长度
(4)limit:集合元素下标的最大值(索引表和嵌套表是不限元素个数的,所以返回null,变长数组返回定义时的最大索引。)
(5)delete([n]):删除集合中的元素,n 是下标
(6)extend(n,[ind]):n 是元素个数,值是ind 这个下标对应的元素。
比如:extend(4,3) :扩展4个元素,值是 a(3) 此处a 是这个表的表名。
(7)next (下标):取当前元素下一个元素的下标
(8)prior(下标):取当前元素上一个元素的下标
3、索引表
下标可以是整数(可以为负)(pls_integer,binary_integer)或者字符串(varchar2),元素个数无限制。
type mytype is table of varchar2(200) index by pls_integerl; (举个声明的例子)
v mytype;
集合中数据的存取:
取: v(下标); 存:v(下标):=值;
4、嵌套表
下标是整数(只能是正数)且下标连续,元素个数无限。
声明举例:type mytype is table of varchar2(100);
v mytype; mytype 是类型名,v 是变量名
数据的存取和索引表相同,但是。
初始化: 变量名 := 类型名;
变量名 := 类型名(值,值,值);
如:v := mytype; 或者 v:=mytype(‘我’,'爱','你');
在数据库中的使用 是 先创建嵌套表类型再建表
删除是先删表,再删除嵌套表类型。
5、变长数组
下标只能是整数(只能为正)(pls_integer,binary_integer),下标连续,且的。可以用在plsql中,也可以用在数据库中。
声明举例:type arrType is varray(10) of varchar2(20);
arr arrType;
使用和嵌套表一样需要初始化,参照嵌套表的初始化。
在数据库中的使用也参照嵌套表在数据库中的使用。
6、bulk collect
可以把一组数据取出来存入一个的变量中。
select .....into 变量 :只能查出保存在变量中。
select .....bulk collect into 集合类型变量:可以查出存放在变量里。
--查询所有员工的名字
declare
type tabType is table of emp.ename%type;
namelist tabType;
begin --注意这里是不需要初始化集合变量的 namelist:=tabType();
select ename bulk collect into namelist from emp;
--打印员工姓名
for i in namelist.first..namelist.last loop
dbms_output.put_line(namelist(i));
end loop;
end;
还可以和游标一起使用
open cur;
fetch cur bulk collect into namelist; (类似这种)
close cur; 游标到这里就没用了。接下来的操作就是嵌套表 namelist 了。
存取数据是 namelist(i) .....
7、批量绑定
语法:forall 变量 in 集合
sql语句; --增insert、删delete、改update
--根据部门编号删除部门下的员工
declare
type tabType is table of dept.deptno%type;
dno tabType;
begin
select deptno bulk collect into dno from dept;
forall i in dno.first..dno.last
delete from emp where deptno=dno(i);
end;
执行完之后 emp 表已经为空了。
可以看一下和for 循环之间的区别。