plsql编程

一、plsql编程

oracle中所拥有的一种编程语言,功能强大

二、存储过程procedure

1.创建存储过程语法

CREATE [OR REPLACE] PROCEDURE pname
   [ (paramName1  [mode1]        type1,
      param2  [mode2]        type2,
      …)]
   ename in varchar2,
   job  out   varchar2,
   sal in out  number
  IS | AS
  [变量定义声明部分,如:
 变量1 INTEGER :=0;
 变量2 DATE;
 ]
  BEGIN
  PL/SQL Block
  END [pname]

–pname:过程名称
–param1、param2:形参名称
–mode1、mode2:参数模式,
          IN (默认)表示输入参数,按值传递方式。
          OUT 表示输出参数,可以理解为按引用传递方式。可以作为存储过程的输出结果,供外部调用者使用。
          IN OUT 即可作输入参数,也可作输出参数。
–type1、type2:参数数据类型
         参数的数据类型只需要指明类型名即可,不需要指定宽度。
         参数的宽度由外部调用者决定。
         过程可以有参数,也可以没有参数
–变量声明块:
       紧跟着的as (is )关键字,可以理解为pl/sql的declare关键字,用于声明变量。
       变量声明块用于声明该存储过程需要用到的变量,它的作用域为该存储过程。另外这里声明的变量必须指定宽度。
遵循PL/SQL的变量声明规范。
–PL/SQL Block:过程语句块 从begin 关键字开始为过程的语句块。存储过程的具体逻辑在这里来实现。:由end   关键字结束。

2.SELECT INTO STATEMENT

  将select查询的结果存入到变量中,可以同时将多个列存储多个变量中,必须有一条
  记录,否则抛出异常(如果没有记录抛出NO_DATA_FOUND)
  例子:
  BEGIN
  SELECT col1,col2 into 变量1,变量2 FROM typestruct where xxx;
  EXCEPTION
  WHEN NO_DATA_FOUND THEN
      xxxx;
  END;
  ...

3.IF 判断

  IF V_TEST=1 THEN
    BEGIN
       do something
    END;
  END IF;

4.while 循环

  WHILE V_TEST=1 LOOP
  BEGIN
 XXXX
  END;
  END LOOP;

5.变量赋值

  V_TEST := 123;

6.例1,功能需求:
要给指定的(通过雇员编号指定)雇员加薪,如果雇员编号在200以内加薪10%,雇员编号大于等于200则加薪15%,创建存储过程的SQL语句如下(HR用户)
CREATE OR REPLACE PROCEDURE raise_salary //raise_salary存储过程的名字
(p_id IN employees.employee_id%TYPE) //p_id存储过程的参数 in从外部传入 ,指定的类型是 //employees这个表中的employee_id的一样的类型
AS

BEGIN
IF p_id >= 200 THEN
BEGIN
UPDATE employees
SET salary = salary * 1.15
WHERE employee_id = p_id;
END;
END IF;
IF p_id < 200 THEN
BEGIN
UPDATE employees
SET salary = salary * 1.10
WHERE employee_id = p_id;
END;
END IF;
END [raise_salary]?

调用存储过程
–在SQL*PLUS中被调用的语句为
?EXECUTE raise_salary(207)
?或EXEC raise_salary(207)
–而在PL/SQL代码中则直接使用
begin
?raise_salary(207)
end

例2 创建存储过程
create or replace procedure p1
(v_a in number,v_b number,v_ret out number,v_temp in out number)
is
declare
v_a number;
v_b number;
v_ret number;
v_temp number:=5;
begin
if (v_a>v_b) then
v_ret:=v_a;
else
v_ret:=v_b;
end if;
v_temp:=v_temp+1;
end;

调用存储过程
declare
v_a number;
v_b number;
v_ret number;
v_temp number:=5;
begin
p1(&v_a的值,&v_b的值,v_ret,v_temp);
dbms_output.put_line(v_ret);
dbms_output.put_line(v_temp);
end;

jdbc调用存储过程:
create or replace procedure emp_sal(eno emp.empno%type,esal out emp.sal%type)
as
begin
select sal into esal from emp where empno=eno;
end;

三、函数function

1.函数和存储过程的区别

2.函数创建
–CREATE [OR REPLACE] FUNCTION fname
[ (param1 [mode1] type1,
param2 [mode2] type2,
…)]
RETURN type
IS | AS
BEGIN
PL/SQL Block
END [fname]
–其中必须注意的是在IS | AS之前要确定返回值类型,在PL/SQL Block块中需要有效的返回语句

3.例:
–假设要创建一个通过员工编号获取部门经理编号的函数,其SQL语句如下(HR用户)
?CREATE OR REPLACE FUNCTION get_manager_id
(p_id IN employees.employee_id%TYPE)
RETURN NUMBER
IS
v_manager_id employees.manager_id%TYPE :=0;
BEGIN
SELECT manager_id INTO v_manager_id
FROM employees WHERE employee_id = p_id;
RETURN v_manager_id;
END get_manager_id;

4.调用函数
不能单独执行函数,只能作为表达式的一部分。
SELECT get_manager_id(207) FROM dual

四、游标cursor(了解)

1.游标的概念
查询的结果集
2.游标优缺点
优点:可以对结果进行方便的操作,适合用小数据量
缺点:不适合大数据量操作,数据量大的时候操作慢,耗占内存和cpu(资源)
由于缺点较明显不建议在真正的项目中使用
3.游标的分类
(1)显式游标
DECLARE
my_toy_price toys.toyprice%TYPE;
CURSOR toy_cur IS SELECT toyprice FROM toys
WHERE toyprice<250;//1.定义游标
BEGIN
OPEN toy_cur; //2.打开游标
LOOP //循环,3.循环使用游标
FETCH toy_cur INTO my_toy_price; //从游标中取出值赋值给my_toy_price
EXIT WHEN toy_cur%NOTFOUND; //当游标中已经没有发现值
DBMS_OUTPUT.PUT_LINE
(‘TOYPRICE=:玩具单价=:‘||my_toy_price);
END LOOP;
CLOSE toy_cur;//4.关闭游标
END;

--显式游标的定义和使用(使用loop循环)
declare
ename emp.ename%type;
esal emp.sal%type;
cursor nscur is select ename,sal from emp;--定义游标
begin
open nscur;--打开游标
loop
fetch nscur into ename,esal;--遍历游标,从游标中获取值赋给2个变量
exit when nscur%NOTFOUND; --当游标遍历完成后退出循环
dbms_output.put_line(‘姓名:‘||ename||‘ 薪资:‘||esal);
end loop;
close nscur;--关闭游标
end;

--显式游标的定义和使用(使用for循环)
declare
ename1 emp.ename%type;
esal emp.sal%type;
cursor nscur is select ename,sal from emp;--定义游标
begin
--open nscur;--打开游标
for ename1 in nscur loop
dbms_output.put_line(ename1.ename||ename1.sal);
end loop;
-- close nscur;--关闭游标
end;
缺点:比较麻烦,步骤繁琐
优点:可以操作(修改、删除)结果集(游标)的内容
(2)隐式游标
select cname into courseName from course

?隐式游标的属性有:
–%FOUND – SQL 语句影响了一行或多行时为 TRUE
–%NOTFOUND – SQL 语句没有影响任何行时为TRUE
–%ROWCOUNT – SQL 语句影响的行数
–%ISOPEN - 游标是否打开,始终为FALSE
BEGIN
UPDATE toys SET toyprice=27 WHERE toyid= ‘P005‘;
//使用了隐式游标,当上面的update语句影响行数>=1,返回true,否则返回false
IF SQL%FOUND THEN
DBMS_OUTPUT.PUT_LINE(‘表已更新‘);
END IF;
END;

五、触发器trigger

1、触发器的概念
数据库一个对象,是由数据库自动管理的,不需要人为去调用
触发器涉及的概念:

?当设置为Statement(默认)时,称为语句触发器,触发器体对于触发事件只执行一次,即使没有行受影响;当设置为Row时,称为行触发器,触发器体对受触发事件影响的每行执行一次

作用:
(1)自动生成数据
(2)自定义复杂的安全权限
(3)提供审计和日志记录
(4)启用复杂的业务逻辑

分类:

2、触发器的创建
(1)语句触发器(默认statement)
–CREATE [OR REPLACE] Trigger tname
timing(AFTER | BEFORE)
event1 [OR event2 OR event3] (INSERT/UPDATE/DELETE)
ON table
trigger_body
?tname表示触发器名字
?timing表示触发时间
?event1、event2和event3表示触发事件
?table表示针对的表,trigger_body表示触发器体(PLSQL表示做什么事)
(2)行触发器(row)
–CREATE [OR REPLACE] Trigger tname
timing
event1 [OR event2 OR event3]
ON table
[REFERENCING OLD AS old | NEW AS new]
FOR EACH ROW
[WHEN(condition)]
trigger_body
?触发器中增加的REFERENCING OLD AS old | NEW AS new表示声明当前行新、老值的别名,默认别名是old和new
?FOR EACH ROW表示此触发器为行触发器
?WHEN(condition)表示触发器的约束

3.例子
(1)语句触发器
–只能在周一到周五的9:00到18:00才可以针对部门表departments进行DML操作
CREATE OR REPLACE TRIGGER dml_depts_time
BEFORE
INSERT OR UPDATE OR DELETE
ON departments
BEGIN
IF TO_CHAR(SYSDATE, ‘HH24:MI‘) NOT BETWEEN ‘08:00‘ AND ‘18:00‘ OR TO_CHAR (SYSDATE, ‘DY‘) IN (‘SAT‘, ‘SUN‘) THEN
RAISE_APPLICATION_ERROR (-20205,‘You may only make changes during normal office hours‘);
END IF;
END dml_depts_time;

测试:?UPDATE departments
SET department_name = ‘IT GROUP‘
WHERE department_id = 60

(2)行触发器
当更改了雇员表中某行的职位编号字段或部门编号字段,自动在职位变迁表job_history中增加一行记录,记录该雇员的职位(包括部门)变迁情况
?CREATE OR REPLACE TRIGGER update_job_history
AFTER
UPDATE OF job_id, department_id
ON employees
FOR EACH ROW
BEGIN
INSERT INTO job_history (employee_id, start_date, end_date, job_id, department_id)
VALUES(:old.employee_id, :old.hire_date, sysdate, :old.job_id, :old.department_id);
END;

测试:
?UPDATE employees
SET department_id = 90

练习:创建一个日志表记录对course表的操作
第一步、创建日志表

第二步创建触发器

第三步测试触发器

原文地址:https://www.cnblogs.com/hglibin/p/9907818.html

时间: 2024-10-17 06:49:20

plsql编程的相关文章

PL-SQL编程基础(4) 异常处理

异常处理: 即使良好的PL-SQL程序也会遇到错误或者未预料的事件,一个优秀的程序都应该能够处理各种出错情况,尽可能的从错误中恢复.程序在运行时出现的错误成为异常.发生异常后,语句讲终止执行,PLSQL会立即将控制权交给PLSQL异常处理部分.Oracle中使用EXCEPTION来处理异常,一般有3种异常错误. 有三种类型的异常错误: 1. 预定义 ( Predefined )错误 ORACLE预定义的异常情况大约有24个.对这种异常情况的处理,无需在程序中定义,由ORACLE自动将其引发. 2

PLSQL编程面向对象的操作

1)了解对象类型组成及其组成部分的作用 2)建立简单的对象类型,并使用 3)建立复杂的对象类型,并使用 4)学会建立参照对象类型,并使用 一.对象类型是用户自定义的一种复合数据类型,封装了数据结构和数据结构的过程和函数,为了描述显示世界对象所抽象出来的具体特征,既有属性又有方法,应该涵盖对象所具有的公共特性,如每个雇员都有编码,姓名,工资,所以定义employee_type类型时就应该包含这些特征,对象实例是对象类型的具体实现,就是根据模型抽象出一个具体的东西,模型造了一辆汽车. 如雇员scot

PL-SQL编程基础(3)

循环结构: 1. LOOP循环结构 语法: LOOP 要执行的语句; EXIT WHEN <条件>   --条件满足则退出循环 END LOOP; 示例:循环输出1-10的整数 DECLARE v_num NUMBER := 1; BEGIN LOOP DBMS_OUTPUT.put_line(v_num); v_num := v_num + 1; EXIT WHEN v_num > 10; END LOOP; END; LOOP结构的弊端:结构不够清晰,EXIT容易漏写. 2.WHIL

plsql编程中游标的使用

游标(Cursor):用来查询数据库,获取记录集合(结果集)的指针,可以让开发者一次访问一行结果集,在每条结果集上作操作. oracle中显示使用游标一般要包含以下5个步骤: 声明一些变量以便存储从游标返回的值. 声明游标,并指定查询. 打开游标. 遍历游标并取得数据. 关闭游标 表结构及数据如下: 1 -- Create table 2 create table EXCHANGETIME 3 ( 4 ID NUMBER(18) default 0 not null, 5 SYSTEM_TYPE

PLSQL编程基础 :分支、循环语句

一.分支语句 set serveroutput on declare num number; begin num:=3; if num = 5 then dbms_output.put_line('这个数字是5'); elsif num >7 then dbms_output.put_line('这个数字大于7'); else dbms_output.put_line('其他数字'); end if; end; 二.循环语句 1.loop循环 set serveroutput on declar

PL-SQL编程基础(2)

一.控制语句 1.if语句 语法: IF <布尔表达式> THEN PL/SQL和SQL语句 END IF; 示例: DECLARE v_count NUMBER := &n; BEGIN IF v_count > 0 THEN DBMS_OUTPUT.put_line('正数'); END IF; END; 判断是否为正整数! 2.if...else... 语法 IF <布尔表达式> THEN PL/SQL 和 SQL 语句 ELSE 其他语句 END IF; 示例

plsql的环境与介绍:环境的搭建和plsql的简单介绍

PLSQL编程 1.环境的搭建 (1)创建一个存储表空间 SQL> conn /as sysdbaConnected. SQL> create tablespace plsql datafile '/u01/oracle/oradata/ORCL/plsql01.dbf' size 1G; Tablespace created. (2)创建PLSQL用户SQL> create user plsql identified by plsql default tablespace plsql;

让我们开始学习plsql吧啵啵啵

最近组里林哥要我学习下外呼的demo,以及obsdemo的修改.看外呼demo及改obsdemo的过程中用到了不少plsql的内容,总是遇到问题东查一点西查一处,知识点很零散,不成系统.因此想系统地学习下plsql编程,下载了plsql程序设计第五版上下两册,从春节前就开始看,目标当然是能在春节前看完(肯定完不成),但是最近用番茄工作法粗略统计发现每个钟只能看最多6页,这个速度让人很忧伤. 不过看还是要看的,尽量在每个番茄钟里提高一点专注力.

PLSQL 过程之间的调用 (实现递归删除目录功能)

在使用PLSQL 编程中需要用到一些递归的操作,这里使用plsql实现递归删除目录 .和大家分享一下. --=======================删除 PROCEDURE DEL_POWER(P_ID INTEGER) IS BEGIN UPDATE EX_SYS_POWER A SET A.YXBZ = 0 WHERE A.ID = P_ID; DEL_CHILDREN_POWER(P_ID); --处理异常 EXCEPTION WHEN OTHERS THEN ROLLBACK; E