12-7 程宗武

Oracle

1. PL/SQL中动态执行SQL语句

EXECUTE IMMEDIATE 动态语句字符串
[INTO 变量列表]
[USING 参数列表]

--例
DECLARE
    e emp%rowtype;
BEGIN
    EXECUTE IMMEDIATE
    'select * from emp where empno = :1'
    INTO e -- 将结果集赋值给变量e
    USING 7788; --给参数传值,sql中的:1类似于占位符?
    dbms_output.put_line(e.empno || ' ---- ' || e.ename);
END;

-- RETURNING 子句
DECLARE
    emp_id NUMBER(4) := 7788;
    salary NUMBER(7,2);
BEGIN
    EXECUTE IMMEDIATE
    'UPDATE emp SET sal = 2222 WHERE empno = :1 RETURNING sal INTO :2'
    USING emp_id
    RETURNING INTO salary; --在动态执行的过程中就将执行过后的结果赋值给salary
    dbms_output.put_line(salary);
END;

2.PL/SQL的异常处理

1.自定义异常

PL/SQL中异常处理的语法
BEGIN
    --可执行部分
    EXCEPTION -- 异常处理开始
    WHEN 异常名1 THEN
    --对应异常处理
    WHEN 异常名2 THEN
    --对应异常处理
    ……
    WHEN OTHERS THEN
    --其他异常处理
END;
-- 例
DECLARE 
  s emp.sal %type;
  myexp EXCEPTION;  --声明异常
BEGIN 
  SELECT SAL INTO s from emp where empno = 7788;
  if s<5000 then 
    raise myexp;
  end if;
  exception
    when myexp then 
      dbms_output.put_line('自定义异常'); --捕获异常
      when others then
         dbms_output.put_line('其他异常');
end;

2.应用程序异常

自定义异常码和异常信息在控制台抛出(异常码的范围在-20000到-20999)之间

DECLARE 
  s emp.sal %type;
  myexp EXCEPTION;
BEGIN 
  SELECT SAL INTO s from emp where empno = 7788;
  if s<5000 then 
    raise myexp;
  end if;
  exception
    when myexp then 
      raise_application_error(-20001,'自定义程序异常');
      when others then
         dbms_output.put_line('其他异常');
end;

image-20201207203854218

3.子程序

以及命名过后的PL/SQL块,编译过后就会存储在数据库中,类似于java中定义了一个方法,可以随时调用。

3.1过程

-- 创建过程的语法 CREATE OR REPLACE 不存在时创建存在时替换
CREATE OR REPLACE PROCEDURE 过程名[(参数名 in/out 数据类型)]
{IS|AS}
--声明部分(参数的声明)
BEGIN
--可执行部分
[EXCEPTION]
--异常处理部分
END [过程名];

--例
CREATE OR REPLACE PROCEDURE Comm(eno IN NUMBER, salary OUT NUMBER)
-- 参数中也可以定义一个默认值 def_num NUMBER default 5000,如果没有传参就使用默认值,如果传了参数就使用传入的参数
AS
       s emp.sal%type;
BEGIN
  SELECT sal, nvl(comm, 0) INTO s, salary FROM emp WHERE empno = eno;
  --nvl(comm, 0) 如果comm就赋值0,避免查询结果为null没有输出
  IF s > 5000 THEN
  salary := salary + 1000;
END IF;
END Comm;
-- 调用过程
DECLARE
   eno NUMBER := 7566;
   d NUMBER; --这里定义一个变量d,便于接收返回值,将d作为参数传入到过程中赋值后返回
BEGIN
  Comm(eno, d);
  dbms_output.put_line(eno || '实际应发的奖金是:' || d);
END;
--sqlplus
EXECUTE DisplaySal;

3.2 函数

函数中必须由返回值(return字句)

-- 创建函数语法
CREATE OR REPLACE FUNCTION 函数名[(过程参数列表)] RETURN 数据类型
{IS|AS}
    --声明部分
BEGIN
    --可执行部分
[EXCEPTION]
    --异常处理部分
END [函数名]; 
--例
CREATE OR REPLACE FUNCTION getRevenue(emp_no NUMBER,base_sal NUMBER default 2000) RETURN NUMBER --返回值类型
IS
       reve NUMBER;
BEGIN
  SELECT sal+comm INTO reve FROM emp WHERE empno=emp_no;
  IF reve>base_sal THEN
     RETURN base_sal*0.2;
  END IF;
      RETURN 0;
EXCEPTION
      WHEN no_data_found THEN
      dbms_output.put_line('没有找到这个员工!');
END getRevenue;

--调用函数
declare
    n number ; --定义一个变量来接收返回值
begin
  n := getRevenue(7499);
  dbms_output.put_line('个人税为:'|| n);
end;
-- 函数也可以被sql语句调用

4.触发器

-- 触发器语法
CREATE [or REPLACE] TRIGGER 触发器名
    {BEFORE | AFTER}
    {DELETE | INSERT | UPDATE [OF 列名]}
ON 表名
    [FOR EACH ROW [WHEN(条件) ] ]
begin
    -- PLSQL 块
End 触发器名;

--例
create or replace trigger testTrigger
       after insert on emp --after 可以替换为before
begin
       dbms_output.put_line('插入了一个员工');
end testTrigger;

伪记录变量

触发语句 :old :new
Insert null 插入的数据
Update 更新以前改行的值 更新后的值
Delete 删除以前的值 null
--例
create or replace trigger addsal
    before update of sal on myemp
for each row
begin
    if :old.sal >= :new.sal then
    raise_application_error(-20002, '涨前的工资不能大于涨后的工资');
end if;
end;

标签

评论

© 2021 成都云创动力科技有限公司 蜀ICP备20006351号-1