ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

PL/SQL编程学习总结

2020-06-09 12:38:04  阅读:286  来源: 互联网

标签:BEGIN END 变量 sal 编程 emp SQL type PL


最近学习了PL/SQL的相关知识,写篇文章记录一下,也当作这两天学习成果的复习回顾啦,如果有问题,可以一起交流学习,互相进步!!!这是第一篇博客,但绝对不会是最后一篇,立个flag以表决心哈哈哈!!!

PL/SQL编程学习总结


PL/SQL(Procedural Language SQL)过程化SQL语言是oracle数据对于sql的扩展,在普通sql语句的使用上增加了编程语言的特点,语法仅适用于oracle数据库。

PL/SQL的基本结构
在这里插入图片描述

变量

变量可以分为:普通型变量,引用型变量,记录型变量以及常量,还有一种支持写入功能的变量:替代变量。

普通型变量

声明变量时可以直接赋初始值

DECLARE
         v_name varchar2(32):=’aaa’;
         v_age number(3):=10;
BEGIN
         v_name:='zhangsan';
         v_age:=25;
         dbms_output.put_line('姓名:'||v_name||'  年龄:'||v_age);
END;

也可以在begin种进行赋值

DECLARE
         v_name varchar2(32);
         v_age number(3);
BEGIN
         v_name:='zhangsan';
         v_age:=25;
         dbms_output.put_line('姓名:'||v_name||'  年龄:'||v_age);
END;

引用型变量

直接把变量类型定义为表中已有字段的类型

DECLARE
     ename emp.ename%type;
     sal emp.sal%type;
     hiredate emp.hiredate%type; 
 BEGIN
     select ename,sal,hiredate into ename,sal,hiredate from emp where empno=7369;
     dbms_output.put_line('姓名:'||ename||'  薪资:'||sal||'  入职日期:'||hiredate); 
 END;

记录型变量

PL/SQL提供了 %ROWTYPE操作符,返回一个记录类型,表示表中的一行记录
记录型变量相当于一条完整的表记录,通过“变量名.列名”获取其值
–记录型变量

DECLARE
    emp_record   emp%ROWTYPE;
BEGIN
	--给变量赋值
    SELECT *  INTO emp_record FROM emp WHERE empno = 7788;
    --打印输出
    DBMS_OUTPUT.PUT_LINE(emp_record.ename||'的工资是:'||emp_record.sal);
END;

常量

在变量名后面加上constant即可。

替代变量

"&n1(替代变量)"运行程序时,会提示用户输入值n1

DECLARE
    v_num1  NUMBER(2) := &n1;
    v_num2  NUMBER(2) := &n2;
BEGIN    
    DBMS_OUTPUT.PUT_LINE(v_num1);
    DBMS_OUTPUT.PUT_LINE(v_num2);
END;

选择循环

分支结构

单分支

需求:输入员工号,判断员工工资, 显示工资小于3000的员工姓名及工资

DECLARE
    v_ename emp.ename%type;
    v_sal emp.sal%type;
BEGIN    
    select ename,sal into v_ename,v_sal from emp where empno=&empno;
    if v_sal<3000 then
      dbms_output.put_line(v_ename||'的薪资是:'||v_sal);
    end if;
END;

双分支

需求:输入员工号,判断员工工资,将工资小于3000的员工工资涨200,并显示涨工资的员工姓名,其他员工显示员工姓名及工资

DECLARE
    v_ename emp.ename%type;
    v_sal emp.sal%type;
    v_empno emp.empno%type:=&empno;  
BEGIN    
    select ename,sal into v_ename,v_sal from emp where empno=v_empno;
    if v_sal<3000 then
       update emp set sal = sal + 200 where empno = v_empno;
       commit;
       dbms_output.put_line(v_ename||'涨工资了');
    else
       dbms_output.put_line(v_ename||'的工资是:'||v_sal);
    end if;
END;

多分支

需求:输入员工号,判断员工工资, 工资小于2000,显示低收入,工资小于6000,显示中等收入,其它显示高收入。

DECLARE
    v_ename emp.ename%type;
    v_sal emp.sal%type;
    v_empno emp.empno%type:=&empno;  
BEGIN    
    select ename,sal into v_ename,v_sal from emp where empno=v_empno;
    if v_sal<2800 then
        dbms_output.put_line(v_ename||'的工资是:'||v_sal||'属于低收入!!');
    elsif v_sal<6000 then 
        dbms_output.put_line(v_ename||'的工资是:'||v_sal||'属于中等收入!!');    
    else
        dbms_output.put_line(v_ename||'的工资是:'||v_sal||'属于高收入!!');    
    end if;
END;

CASE分支处理等值

需求:输入成级等级,判断属于哪个层次,并打印输出(录入的字符串需要加双引号)

DECLARE 
       v_grade char(1) := &no;
BEGIN
       CASE v_grade
            WHEN  'A'  THEN
                  DBMS_OUTPUT.PUT_LINE('优秀');
            WHEN  'B'  THEN
                  DBMS_OUTPUT.PUT_LINE('中等');     
            WHEN  'C'  THEN
                  DBMS_OUTPUT.PUT_LINE('一般'); 
            ELSE
                  DBMS_OUTPUT.PUT_LINE('输入有误');    
       END CASE;              
END;

CASE分支处理非等值

需求:输入员工号,获取员工工资,判断工资,如果工资小于1500,补助加100,如果工资小于2500,补助加80,如果工资小于5000,补助加50.

DECLARE       
       v_sal     emp.sal%TYPE;
       v_empno   emp.empno%TYPE := &no;
BEGIN
       SELECT sal
       INTO   v_sal
       FROM   emp
       WHERE  empno = v_empno;
       CASE 
              WHEN v_sal<1500 THEN
                   UPDATE emp set comm = nvl(comm,0)+100 WHERE empno = v_empno;
              WHEN v_sal<2500 THEN
                   UPDATE emp set comm = nvl(comm,0)+80 WHERE empno = v_empno;     
              WHEN v_sal<5000 THEN
                   UPDATE emp set comm = nvl(comm,0)+50 WHERE empno = v_empno;                   
       END CASE;
       COMMIT;
END;

循环结构

需求:打印1-10的数字

LOOP循环

DECLARE
       V_COUNT NUMBER(2) := 1;
BEGIN
     LOOP
         DBMS_OUTPUT.put_line(V_COUNT);
         EXIT WHEN V_COUNT=10;
         V_COUNT := V_COUNT+1;
     END LOOP;
END;

While循环

DECLARE
       V_COUNT NUMBER(2) := 1;
BEGIN
     WHILE V_COUNT<=10 LOOP
           DBMS_OUTPUT.put_line(V_COUNT);
           V_COUNT := V_COUNT+1;
     END LOOP;
END;

For循环

DECLARE
       
BEGIN
     FOR i IN 1..10 LOOP
         DBMS_OUTPUT.put_line(i);
     END LOOP;
END;

对于for循环不需要提前定义变量 in后的1代表起始值 10代码终止值 每次递增1 不需要写变量的改变

For循环倒叙

DECLARE
       
BEGIN
     FOR i IN REVERSE 1..10 LOOP
         DBMS_OUTPUT.put_line(i);
     END LOOP;
END;

双重for循环

嵌套循环需要使用标号 <<label_name>>

DECLARE
    
BEGIN
    <<outter>>
    FOR i IN 1..5 LOOP
        DBMS_OUTPUT.PUT_LINE('外'||i);
        <<inter>>
        FOR j IN 1..2 LOOP        
          DBMS_OUTPUT.PUT_LINE('---内'||j);
          EXIT outter WHEN i=4;
        END LOOP inter;
     END LOOP outter;
END;

退出循环

EXIT :直接退出循环
EXIT WHEN :满足一定条件退出循环

游标

游标是用来在PL/SQL中操作查询的结果集
语法:cursor 游标名(参数) is 查询的结果集

使用步骤:

  1. 声明游标
  2. 打开游标 open 游标名
  3. 从游标中取数据 fetch 游标名 into 变量
    fetch一次就从游标中取一条记录
    游标名%found:从游标中找到了数据
    游标名%notfound:从游标中没有找到数据
  4. 关闭游标 close 游标名

注意:定义游标参数时不能设置长度

存储过程

存储过程(Stored Procedure)是,一组为了完成特定功能的SQL 语句集,存储在数据库中,经过第一次编译后调用不需要再次编译,用户通过指定存储过程的名字来执行它。

语法形式如下:
CREATE [OR REPLACE] PROCEDURE 存储过程名
[( param1 [mode1] type1, param2 [mode2] type2, …)]
IS | AS 变量声明

BEGIN 业务处理

END;

param1、param2:形参名称
mode1、mode2:参数模式,包括IN(默认)、OUT
type1、type2:参数数据类型

需求:根据员工编号输出员工的姓名、工资和入职时间

create procedure P_GETEMP(eno in emp.empno%type) 

is
  v_name emp.ename%type;
  v_sal emp.sal%type;
  v_hiredate emp.hiredate%type;
begin
     select ename,sal,hiredate into v_name,v_sal,v_hiredate 
     from emp where empno=eno;
     dbms_output.put_line(v_name);  
     dbms_output.put_line(v_sal); 
     dbms_output.put_line(v_hiredate); 
end ;

存储过程调用
PL/SQL调用存储过程,如果没有变量声明,DECLARE可以省略

DECLARE

BEGIN 
  P_GETEMP(7936);    
END;

函数

函数和存储过程存在以下区别但本质上没什么区别。
在这里插入图片描述

语法形式如下
CREATE [OR REPLACE] FUNCTION 函数名
[( param1 [mode1] type1, param2 [mode2] type2, …)]
return type
IS | AS 变量声明
BEGIN 业务处理 END;

param1、param2:形参名称
mode1、mode2:参数模式,包括IN(默认)、OUT
type1、type2:参数数据类型

需求:查询指定员工的年薪,参数员工的编号,返回年薪。

create or replace function f_gettotalsal(vempno in emp.empno%type) 
return number
is
  vtotalsal emp.sal%type;
begin
    select sal*12+nvl(comm,0) into vtotalsal from emp where empno=vempno;
    return vtotalsal;
end;

函数调用

declare
vtotalsal number;
begin 
  vtotalsal := f_gettotalsal(7369);
  dbms_output.put_line(vtotalsal);    
end;

注意:自定义的函数和oracle提供的函数一样的使用方式

触发器

触发器是一个数据库对象,当特定的事件发生时隐式的执行,比如在一个表上发生插入、更新或删除的事件(进行DML操作时),数据库触发器会隐式执行。
在这里插入图片描述

语法形式如下
CREATE [OR REPLACE] Trigger 触发器名字
	timing
	    event1 [OR event2 OR event3]
	    ON table
   [for each row] [when 条件  [old.pid>7900]] old在plsql语句中前面要加上: 即:old  :new
	trigger_body

timing表示触发时间
event1、event2和event3表示触发事件
table表示针对的表,
for each row 每行数据就会触发一次该触发器
trigger_body表示触发器体

需求:不允许在周日修改emp表

create or replace trigger auth_secure 
before 
insert or update or DELETE
on emp
begin
  IF(to_char(sysdate,'DY')='星期日') THEN
    RAISE_APPLICATION_ERROR(-20600,'不允许在周日修改emp表');
  END IF;
END;

注意:
RAISE_APPLICATION_ERROR()是 oracle内置的一个过程 第一个参数是自定义的错误码

异常处理

程序运行过程中发生的意外

ZERO_DIVIDE --ORA-01476-- 程序尝试除以 0
VALUE_ERROR --ORA-06502-- 类型转换错误
NO_DATA_FOUND --ORA-01403-- 未找到行
TOO_MANY_ROWS --ORA-01422–SELECT INTO 语句返回多行数据
OTHERS 其他的异常

DECLARE
   --变量的声明
BEGIN  
    --业务处理
EXCEPTION 
          WHEN 异常 then
          ...
          WHEN 异常2 then
          ...
          WHEN others then 
          ....
END;

需求:编写一个函数 求2个数的商

create or replace function f_mod(v1 in number,v2 in number) return number
is
 v_ret number;
begin
     v_ret := v1 / v2;
     return v_ret;
exception
      when ZERO_DIVIDE then
      RAISE_APPLICATION_ERROR(-20600,'除数不能为0');   
end;

select f_mod(5,0) from dual

SQL优化

不要让Oracle做的太多

1.避免复杂的多表关联
2.避免使用“ * ”
3.避免使用耗费资源的操作
4.用exists替换distinct
5.用UNION—ALL替换UNION

给优化器更明确的命令
1.自动选择索引
2.避免在索引列上使用函数或者列
3.避免在索引列上使用not,前置通配符,is null等
4.避免出现索引列自动转换
因为上面的操作,都会使索引失去作用,然后对表进行逐一遍历

减少访问次数
当执行每条SQL语句时, ORACLE都会在内部执行了许多工作,例如:解析SQL语句、估算索引的利用率、绑定变量、读数据块等等。由此可见,减少访问数据库的次数,就能减少ORACLE的实际工作量。

标签:BEGIN,END,变量,sal,编程,emp,SQL,type,PL
来源: https://blog.csdn.net/qq_45266900/article/details/106626106

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有