数据库编程 PLSQL块

 基本语法

declare
--声明
a int;
b int;
res int;
begin
--逻辑开始执行
 a:=&a;--输入a赋给a
 b:=&b;
 res:= a+b;
 dbms_output.put_line(res);
 --输出到控制台
end;
--代码块的结束

在查看里打开DBMS输出再连接到用户,就可以看到结果了

如果在其中使用select语句为

select 表的列名 into 定义的变量名 from 表名 where 
--意思是把选出的结果赋值给变量

如果变量类型是表的某列的的类型则

可声明为

name emp.ename%type;

如果是想要表的一行则

tmp emp%rowtype;

但输出时需要将自己想输出的选出来,不能直接写变量

declare
name emp.ename%type;
sal emp.sal%type;
tmp emp%rowtype;
begin
--逻辑开始执行
 name:=&name;
 select sal into sal from emp where ename=upper(name);
 select * into tmp from emp where ename=upper(name);
dbms_output.put_line(sal);
dbms_output.put_line(tmp.ename||'---'||tmp.sal);
 --输出到控制台
end;

注意输入的是字符串的时候需要自己写单引号

数据库编程 PLSQL块_第1张图片

循环

loop

loop
  循环内容
  exit when 结束条件
  循环内容
  end loop

declare
x int;
e int;
begin
x:= 1;
e:= 5;
loop
  dbms_output.put_line(x);
  exit when x=e;
  x:=x+1;
  end loop;
end;

for

declare 
(记得定义)
begin
for x in 1..10 
  loop 
   循环内容
  end loop;
end

while

 while x <=10 
  loop
    循环内容
  end loop;

分支 if....else

if 判断1 then        语句1;
elsif 判断2 then     语句2;
elsif 判断3 then     语句3;
else    语句4;
  end if;

练习

1编写一个程序··PLSQL·块

2向emp·表中插入10条数据

3员工编码·从·1000·开始·1000·1001-1002...·[序列]

4员工姓名·为·3-5位随机数值或字母组合,·姓名不能相同.......[GUID·截取字符串

5员工工作·从·emp·表中的·job·随机赋值,job·不能为·MANAGER·…·[随机数排序,伪列第一个]

6员工领导和部内编码,-根据·job·指定,·随机一个即可

7入职时间·为·10.-·20·年之间·

8薪资·为所在部内的·最低和最高之间··1000-3000.

9如果·job·为·SALESMAN·可以设置奖金,奖金为·公司最低和最高奖金之间

--序列
create sequence x_id
start with 1000
increment by 1
maxvalue 1010
nocache;
declare
s emp.sal%type;
b emp.sal%type;
tmp emp%rowtype;
x int;
begin
for x in 1..9
loop 
--随机截取3-5个不一样的字符当名字
select substr(sys_guid(),10,trunc(dbms_random.value(3,5))) into tmp.ename from dual;
--随机选取职业
select job into tmp.job from 
(select job  from emp where job !='MANAGER' order by dbms_random.value(1,50))
where rownum =1 ;
select mgr into tmp.mgr from(select mgr from emp where emp.job=tmp.job order by dbms_random.value(1,50)) where rownum =1;
--部门号
select deptno into tmp.deptno from(select deptno from emp where emp.job=tmp.job  order by dbms_random.value(1,50)) where rownum =1;--
select to_date(to_char(trunc(dbms_random.value(2014,2004)))||'-'||to_char(trunc(dbms_random.value(1,12)))||'-'||to_char(trunc(dbms_random.value(1,30))),'yyyy-mm-dd') into tmp.hiredate from dual;--8
select max(sal) into s   from emp  group by deptno having emp.deptno=tmp.deptno ;
select min(sal) into b   from emp  group by deptno having emp.deptno=tmp.deptno ;
select trunc(dbms_random.value(b,s)) into tmp.sal  from dual;
select max(co)  into s  from (select max(comm) co  from emp  group by deptno) ;
select min(co)  into b  from (select min(comm) co  from emp  group by deptno) ;
if tmp.job='SALESMAN' then 
select trunc(dbms_random.value(b,s)) into tmp.comm  from dual;
else  tmp.comm := NULL;
end if;
dbms_output.put_line( tmp.ename||'--'||tmp.job||'--'||tmp.mgr||'--'||tmp.hiredate||'--'||tmp.sal||'--'||tmp.comm||'--'||tmp.deptno);

insert into emp values(m_id.nextval,tmp.ename,tmp.job,tmp.mgr,tmp.hiredate,tmp.sal,tmp.comm,tmp.deptno);
end loop;
end;

游标

相当于指针,用fetch into把获取到的放到变量,要记得打开和关闭

在声明中定义

declare 
  cursor mycur is select * from emp; 
  tmp emp%rowtype;
begin
  open mycur;
  fetch mycur into tmp;
  dbms_output.put_line(tmp.ename);
  close mycur;
end;

--用for来遍历数据集,默认自动打开游标

  for tmp in mycur 
  loop 
    dbms_output.put_line(tmp.ename);
  end loop;

游标的状态
NOTFOUND --如果FETCH语句失败,则该属性为"TRUE",否则为"FALSE";
FOUND --如果FETCH语句成果,则该属性为"TRUE",否则为"FALSE";
ROWCOUNT --返回游标当前行的行数;
ISOPEN --如果游标是开的则返回"TRUE",否则为"FALSE";

将定义声明成一个类型
--将定义声明成一个类型   ref 游标 
declare
 type 类型名 is ref cursor; 
 变量名 类型名;
 v_sql varchar2(100);
begin
 v_sql :='select * from emp';--把语句放进去
  open 变量名 for v_sql; --打开游标
 close 变量名;
end;

--可以用游标的状态来决定什么时候退出循环
 loop -- 遍历游标
    fetch v_vur into v_row; --读取了一行数据
    exit when v_vur%notfound; -- fetch 失败退出循环, 没有数据了
    dbms_output.put_line(v_row.ename);
  end loop
把定义放在包里
create package pk_commons is type mycur is ref cursor;
end;

--然后可以在程序包查找

到时候可直接写类型的时候
变量名  pk_commons.mycur;

函数

有且仅有一个返回值

create or replace function fn(x int ,y int) return int  ----函数声明,int只是声明类型如果是varchar2,不用写成varchar2(10),如果没有参数传则不用写括号
as
--对变量的声明
begin
--代码块
end;
--当这个函数运行会保存成一个文件
select * from user_procedures;


或者写成
create function fn(x int ,y int) return int
is 
begin
end;

存储过程

作用是给第三方调用,给第三方提供接口,有多个输出结果

在进行传参和结果类型的定义的时候,会将他们放在一起用in表示入参,out表示出参,inout既当入参又当出参。

create or replace procedure page(
p_current in int,--收到目前在第几页
p_count in int,--一页有几条数据
p_page out int,--输出数据总共多少页
p_cur out pk_commons.mycur --之前给游标定义了一个包create package pk_commons is type mycur is ref cursor;
)
as
p_total int;
p_sql varchar2(1000);--给游标定义的sql语句
p_s int;--这页开始时所处的总数据的第几条
p_e int;--这页结束时所处的总数据的第几条
begin
 select count(ename) into p_total from emp;--找到总数据共有多少条
 p_page := ceil(p_total/p_count);--算出页数
 p_s:= (p_current-1)*p_count;
 p_e:= p_current*p_count;
 p_sql := 'select * from 
 (select e.*,rownum rn from emp e where rownum<='||p_e||')t where t.rn>'||p_s;
 open p_cur for p_sql;--打开游标
 end;

编译成功后会在

数据库编程 PLSQL块_第2张图片

记得要给该用户授权

grant DEBUG CONNECT SESSION,DEBUG ANY PROCEDURE to scott;

然后可以对他进行调试,填入输入值

数据库编程 PLSQL块_第3张图片​​​​​​​

在下方的输出变量中查看

数据库编程 PLSQL块_第4张图片

异常

CURSOR_ALREADY_OPEN             试图"OPEN"一个已经打开的游标

DUP_VAL_ON_INDEX                试图向有"UNIQUE"中插入重复的值

INVALID_CURSOR                  试图对以关闭的游标进行操作

INVALID_NUMBER                  在SQL语句中将字符转换成数字失败

LOGIN_DENIED                    使用无效用户登陆

NO_DATA_FOUND                   没有找到数据时

NOT_LOGIN_ON                    没有登陆Oracle就发出命令时

PROGRAM_ERROR                   PL/SQL存在诸如某个函数没有"RETURN"语句等内部问题

STORAGE_ERROR                   PL/SQL耗尽内存或内存严重不足

TIMEOUT_ON_RESOURCE             Oracle等待资源期间发生超时

TOO_MANY_ROWS                   "SELECT INTO"返回多行时

VALUE_ERROR                     当出现赋值错误

ZERO_DIVIDE                     除数为零

你可能感兴趣的:(数据库)