Plsql

plsql  ---过程化查询语言
---plsql 才是 oracle 核心语言
---plsql 自己的核心  变量  判断  循环
---plsql 就是 sql 的一个进阶

程序块  


1. 无名块 :没有名字 ,只能执行一次,不能存储
2. 有名块 :有名字的 , 永久保存到数据库中,随时拿来调用 to_char 

无名块的结构

declare -------------------声明部分(可选)
--声明变量、变量类型、游标...
begin ---------------------程序的开始,执行部分(核心)

--可以直接使用dml语句 delete from emp where deptno = 10;
--可以直接使用tcl语句 commit;
--可以使用select into语句
--不能直接使用ddl语句,但是可以通过动态sql来实现ddl语句。

exception -----------------异常部分(可选)
end -----------------------结束部分,必须有
declare
 变量1  变量类型; ---在程序块当中每完成一句话 必须加;
 变量2  变量类型;
 .............................. 
begin

end;

给变量赋值 

1. 在 begin 里面 用 := 给变量赋值

declare
 V_a varchar2(30);
begin
  V_a:='hello world'; 
  dbms_output.put_line(V_a);
end;

2. 在 declare 后面 用 := 赋值 

declare
 V_a varchar2(30) := 'hello world'  ; ---初始值   
begin
  dbms_output.put_line(V_a);
end;

3. 通过 select into 语句 给变量赋值 

declare
 V_ename  varchar2(30);
 V_job    varchar2(20);
 V_sal    number;---默认的是38 个长度
begin
  select ename,job,sal 
    into V_ename,V_job,V_sal ---注意 变量的个数 顺序 属性 要和 查询结果一致
     from emp 
      where empno=7839;
  dbms_output.put_line( V_ename||V_job||V_sal); --变成1个字符
end;
---注意 此时 变量 只能接受一个值,,只能处理一行数据

4.手动输入 &

declare
 V_empno number := '&提示词1' ;
 V_ename varchar2(30) := '&提示词2';---建议加上单引号
                                    ---提示词不能一样
 V_ename varchar2(20);
 V_job   varchar2(30);
 V_sal   number;
begin
  select ename,job,sal 
   into V_ename,V_job,V_sal 
    from emp 
     where empno=V_empno;   
 dbms_output.put_line(V_ename||V_job||V_sal);    
end;
-----------(注:若提示词相同,则输入弹窗只有一个输入口,输入一个值同时给两个变量赋值)

变量类型 

number  varchar  date -----普通类型
1. 引用型变量类型 %type %rowtype
2. 记录型变量类型 record

%type

指引用型变量类型,可以引用某张表的某字段的属性,还可以引用已经存在的变量类型      
优点: 1 . 不需要知道字段的属性的
            2. 可以跟随字段的属性发生变化

    语法:  

declare
 变量1  表名.列名%type; --引用某张表的某字段的属性
 变量2  变量1%type;   ---引用已经存在的变量类型
begin
end;
%rowtype  


   row--行
   定义:是引用某张表的一行(所有字段)的数据类型 --复合类型 ,此时变量是复合变量
   优点
    1. 可以不需要知道表的字段的属性
    2. 也可以跟着改变
    缺点
    1. 固定不灵活

declare
 V_emp    emp%rowtype; ---引用emp所有字段的属性 表名%rowtype
                       ---8个属性 复合类型
                       ---v_emp  复合变量 8个小变量 V_emp.empno  V_emp.ename v_emp.job....
 V_dname  dept.dname%type;
begin
 select ename,job,sal,emp.deptno,dname
  into  V_emp.ename,V_emp.job,V_emp.sal,V_emp.deptno,V_dname
   from emp 
    left join dept 
     on emp.deptno=dept.deptno
      where empno=7566 ;   
  dbms_output.put_line(V_emp.ename||V_emp.job||V_emp.sal||V_emp.deptno||V_dname);   
end;
--复合变量在使用时候 要拆开使用

record 

 优点 灵活 用几个变量写几个
 缺点 声明时候麻烦一点
语法:

declare
 type 类型名 is record (变量1 变量类型,变量2 变量类型,变量3 变量类型....);----声明出一个变量类--复合类型
 变量名 类型名;  --复合变量 变量名.变量1   变量名.变量2 ....
begin
end;

在程序块当中  dml语句的使用


insert  .
update 
delete

returning  列名1,列名2 ......  into 变量1 ,变量2 .....

--注意: 在 insert 插入数据的时候 returning 是将插入的数据交给变量

---update 的时候  returning 是将修改后的数据 交给变量

---delete 的时候 returning  是 删除的数据交给变量

ddl语句在程序块当中的使用


--需要动态sql 来实现

动态sql : 是指 sql语句 加上单引号 交给变量

语法:

declare
 变量    varchar2(300);  --------1. 声明变量
begin
 变量 :='sql语句';        -------2.定义动态sql 
                          -------1.sql必须是正常的能执行的sql语句

 execute immediate 变量   -------3.立即执行动态sql 
    [into  变量1.......] ;   -------将执行的结果交给变量1.....

end;

判断 if --分支判断 

语法

declare 
begin
  if   条件1.... 
   then 执行代码1 ;-----当满足条件1 时要执行的代码
    elsif 条件2 .......
     then 执行代码2 ;---当满足条件2 时要执行的代码
    elsif 条件3 .......
     then 执行代码3 ;---当满足条件3 时要执行的代码
    elsif 条件4 .......
     then 执行代码4 ;---当满足条件4 时要执行的代码 
      .....................
    else  其他执行代码;---当不满足以上所有条件时 要执行的代码
   end if; ------------结束判断      
--注意:当满足了其中一个条件,就要执行对应的代码,然后直接执行 end if 
end;

循环 

1. loop 循环 :是一个无限循环 死循环 ,必须配合退出循环条件
2. while 循环 :自带条件的循环
3. for 循环 :最主要的 最常用的 最好用 最牛的循环

loop 循环

是一个无限循环 死循环 ,必须配合退出循环条件

语法:

declare
begin
  loop             ---------循环的开始 
                   ---------1.循环主体  循环的内容  
                   ---------2.控制循环次数 --可选
     exit when 条件;  -------3.按照条件退出 满足条件退出循环
  end loop;  ---------------结束循环
end;

while 循环

语法:

declare
begin 
 while 条件    ----------------------进入循环的条件  满足条件才能进入循环
  loop         ----------------------循环的开始
   ----------------------------------1.循环主体 循环的内容
   ----------------------------------2.控制循环次数 可选
  end loop;   -----------------------结束循环
end;

for 循环*

语法:

declare
begin
  for  变量名 in x..y | (sql语句) | 游标  -----------------for循环自带的变量      
   loop  
     ----------------循环主体 循环的内容
   end loop;
end;

for循环的反转reverse

declare
begin
  for i in  reverse 1..100 loop
   if mod(i,2)=1 then 
      dbms_output.put_line(i);
   end if;
  end loop;   
end;

for 循环后 跟SQL 语句

语法:

begin
   for 变量 In (sql语句) ---sql语句 必须加() ,正常的语句 select ename from emp whenre empno=V_empno
    loop 
     ---循环主体
    end loop;
end;
declare
begin
  for i  in  (select ename,job from emp ) ----此时 变量 是复合变量  i.ename   i.job
    loop
      dbms_output.put_line(   i.ename||i.job  );
    end loop;   
end;

游标 cursor 


    定义:游标本质上是一个变动的光标,指向查询结果的每条数据,初始的时候指向第一条数据
    作用:处理多行数据 ----for sql 

语法:

declare
 cursor 游标名 is sql语句;  ----1.声明游标 定义游标
begin
 open 游标名;              -----2.打开游标
  fetch 游标名 into 变量名.... ; -----3. 提取游标 ***********
  ---1. 提取游标  2. 将提取的值交给变量 3.指针下一
 close  游标名;              --------4. 关闭游标
end;

---游标 需要配合循环来使用

游标的属性
1. 游标名%found  --当游标有值的时候返回 true 真  条件成立
2. 游标名%notfound --当游标没有值的时候返回 true 真  条件成立
3. 游标名%isopen  ---判断游标是否打开  如果是 则返回 true 
4. 游标名%rowcount  --记录游标处理的行数  返回的是数值

for 配合游标
1. for  循环会自动的打开和关闭游标
2. for  循环会自动的 fetch 游标

declare
 cursor c1 is select ename,job,sal from emp; --声明游标
begin
  for i in c1 ---游标 
    loop
      dbms_output.put_line(i.ename||i.job||i.sal);
    end loop;
end;

等价写法

declare
begin 
  for i in (select ename,job,sal from emp ) 
   loop
    dbms_output.put_line(i.ename||i.job||i.sal);
   end loop;   
end;

有名块

函数 function


自定义函数
--特点:有且只有一个返回值
mod(4,2) --number

创建函数 语法:

create [or replace] function  函数名(形参1 形参类型,形参2 形参类型.....)
return 返回值的类型
--------------------------------------上面的类型不能写长度
is
  --声明部分
begin
  --核心 实现函数的过程  
  return  结果; -----函数最终的得到的结果
end;
---当使用函数的时候 放入的参数的个数顺序属性 要和创建时一致

存储过程 


--数据库对象之一
--和函数相比 没有返回值 
--存储过程 是将 要执行的任务或者程序 存储起来
--随时拿来调用以及可以外接其他工具
--存储过程要比普通的代码块效率高

创建存储过程 procedure:

create [or replace] procedure 存储过程名(形参1 形参类型,形参2 形参类型.....)
is
begin
end;

调用存储过程
1. call 存储过程();
2. 程序块调用


存储过程的三种参数
IN  输入参数   --可以省略不写, 默认就是 in 输入参数
OUT  输出参数
IN OUT  输入输出参数

--OUT 输出参数
--打印输出7788的员工姓名(用输出参数方式来做)
CREATE OR REPLACE PROCEDURE sp_emp_out(v_name OUT VARCHAR2)
IS
BEGIN
  SELECT ename INTO v_name FROM emp WHERE empno=7788;
END;

--调用
DECLARE
v_name VARCHAR2(20);
BEGIN
  sp_emp_out(v_name);
  DBMS_OUTPUT.PUT_LINE(v_name);    
END;

触发器  

[数据库对象之一]  由对一张表的dml操作引起的一系列触发事件
--关键字  TRIGGER
创建语法:

CREATE OR REPLACE TRIGGER 触发器名称 
AFTER | BEFORE  
[UPDATE] [OR] [DELETE] [OR] [INSERT]
ON 表名  
[FOR EACH ROW]
BEGIN
  --触发代码
END;
----------------------------------------------------------------
FOR EACH ROW 行级触发器  --dml影响了几行数据,触发器就会执行几次
如果不加 FOR EACH ROW 表级触发器  --无论dml影响了多少行数据, 触发只会执行一次!!!

触发器三种判断属性
 

inserting  --判断当前操作是否为 insert ,若是 返回TRUE
updating --判断当前操作是否为 update,若是 返回TRUE
deleting --判断当前操作是否为 delete ,若是 返回TRUE

行级触发器的2大属性:
 

:NEW   -- 更新之后的每一行数据
:OLD    --更新之前的每一行数据
------
UPDATE
:NEW  有
:OLD  有
-----
DELETE
:NEW  无
:OLD  有
-----
INSERT
:NEW  有
:OLD  无

异常  EXCEPTION

异常: 网络异常,硬件异常,软件异常
软件异常:预定义异常, 非预定义异常, 自定义异常

预定义异常   --数据库自带异常
异常组成: 异常代码,异常信息

DECLARE
v_name VARCHAR2(20);
BEGIN
  DBMS_OUTPUT.PUT_LINE(1/0); 
  SELECT ename INTO v_name FROM emp;
EXCEPTION   --异常处理(不是修正错误!!!)
   WHEN ZERO_DIVIDE THEN
     dbMS_OUTPUT.PUT_LINE('除数为0,请修改');
   WHEN TOO_MANY_ROWS THEN
      dbMS_OUTPUT.PUT_LINE('返回多行');  

未知异常: OTHERS 
错误信息: SQLERRM 
错误代码: SQLCODE 

DECLARE
v_name VARCHAR2(20);
BEGIN
  DBMS_OUTPUT.PUT_LINE(1/0); 
  SELECT ename INTO v_name FROM emp;
EXCEPTION   --异常处理(不是修正错误!!!)
   WHEN OTHERS  THEN
     dbMS_OUTPUT.PUT_LINE(SQLCODE||'   '||SQLERRM);
END;

非预定义异常

DECLARE
myexp   EXCEPTION ;  --第一步   定义一个异常名称
PRAGMA EXCEPTION_INIT(myexp,-00904) ;   --第二步 将异常的名字和异常代码进行绑定 
V_J VARCHAR2(11);
BEGIN
  SELECT JJJJ INTO V_J FROM EMP;
  EXCEPTION
    WHEN OTHERS THEN
      dbMS_OUTPUT.PUT_LINE(SQLCODE || SQLERRM);       
END;

自定义异常

DECLARE
myexp EXCEPTION;
PRAGMA EXCEPTION_INIT(myexp,-20001);  --自定义异常代码范围  [-20001  --  -20999]
BEGIN
  raise_application_error(-20001,'自定义');--自定义异常需要手动抛出
    EXCEPTION
    WHEN OTHERS THEN
      dbMS_OUTPUT.PUT_LINE(SQLCODE || SQLERRM); 
END;

 由两部分组成  包头和包体  (一系列 存储过程或函数的集合)
PACKAGE   包头
PACKAGE BODY 包体

第一步  创建包头

create or replace package 包名
is
  声名部分;--可以声名常量,变量等
  存储过程的声名;--只需要声名它名字和参数,不需要实现
  函数的声名; --函数声名名字,参数和返回值类型
end 包名;
---------------------------------------
CREATE OR REPLACE PACKAGE pak_tool
IS
  PROCEDURE SP_TEST1(V_DEPTNO NUMBER);
  PROCEDURE SP_TEST2(V_EMPNO NUMBER);
  FUNCTION F_EMP(V_EMPNO NUMBER) RETURN NUMBER;
END;

第二步 创建包体

create or replace package body 包名     --名字跟包头的名字一致
IS
    声名部分;--包声名中的变量都要在这里声名,其次还可以声名一些包声名中没有变量
    存储过程的实现;
    函数的实现;
end;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值