PLSQL——06、存储过程

时间:2022-06-15 00:20:39

练习 1:导入型形式参数(in类型)

CREATE OR REPLACE PROCEDURE raise_salary
(p_id IN emp.empno%TYPE)
IS
--变量声明
BEGIN
  UPDATE emp SET sal = sal * 1.1
  WHERE empno = p_id;
END raise_salary;
/

存储过程的调用:

--方法一:
EXECUTE raise_salary (7839);
--方法二:
declare
  v_empno emp.empno%type :=&p_empno;
begin
  RAISE_SALARY(v_empno);
end;
/

SQL>SHOW ERROR --查看编译错误;

练习 2:导出型形式参数(out类型)

CREATE OR REPLACE PROCEDURE query_emp
(p_id IN emp.empno%TYPE,
  p_name OUT emp.ename%TYPE,
  p_salary OUT emp.sal%TYPE,
  p_comm OUT emp.comm%TYPE)
IS
BEGIN
  SELECT ename, sal, comm
  INTO p_name, p_salary, p_comm
  FROM emp
  WHERE empno = p_id;
END query_emp;
/

存储过程的调用:

----方法一:
VARIABLE g_name VARCHAR2(25)
VARIABLE g_sal NUMBER
VARIABLE g_comm NUMBER
EXECUTE query_emp(7369, :g_name, :g_sal, :g_comm);
PRINT

----方法二:
declare
  v_empno emp.empno%type:=7499;
  v_sal emp.sal%type;
  v_ename emp.ename%type;
  v_comm emp.comm%type;
begin
  query_emp(v_empno,v_ename,v_sal,v_comm);
  dbms_output.put_line(v_ename|| ||v_sal|| ||v_comm);
end;
/

练习 3:导入/导出型形式参数(in/out类型)

CREATE OR REPLACE PROCEDURE format_phone
(p_phone_no IN OUT VARCHAR2)
IS
BEGIN
p_phone_no := ( || SUBSTR(p_phone_no,1,3) ||
) || SUBSTR(p_phone_no,4,3) ||
- || SUBSTR(p_phone_no,7);
END format_phone;
/

存储过程的调用:

----方法一:
VARIABLE g_phone_no VARCHAR2(15);
BEGIN
:g_phone_no:=8006330575;
format_phone (:g_phone_no);
END;
/

----方法二:
VARIABLE g_phone_no VARCHAR2(15);
:g_phone_no:=8006330575;
PRINT g_phone_no
EXECUTE format_phone (:g_phone_no)
PRINT g_phone_no

练习 4:带有default值的参数

----创建序列:
create sequence departments_seq start with 50;

CREATE OR REPLACE PROCEDURE add_dept
(p_name IN dept.dname%TYPE DEFAULT unknown,
 p_loc IN dept.loc%TYPE DEFAULT BJ)
IS
BEGIN
  INSERT INTO dept(deptno,
  dname, loc)
  VALUES (departments_seq.NEXTVAL, p_name, p_loc);
END add_dept;
/

----存储过程的调用:
BEGIN
add_dept;
add_dept (TRAINING, SH);
END;
/

练习 5:校验数据存在否

CREATE OR REPLACE PROCEDURE valid_deptno
    (v_deptno IN d.deptno%TYPE,V_RETURN OUT BOOLEAN)
  IS    
    v_dummy  VARCHAR2(1);
  BEGIN
    SELECT x
    INTO   v_dummy
    FROM   d
    WHERE  deptno = v_deptno;
    IF SQL%FOUND THEN
     V_RETURN:=TRUE;
    END IF;
  EXCEPTION
    WHEN NO_DATA_FOUND THEN 
      V_RETURN:=FALSE;
  END valid_deptno;
/

----调用
DECLARE
  V_FLAG BOOLEAN;
BEGIN
  valid_deptno(90,V_FLAG);
  if v_flag then
    DBMS_OUTPUT.PUT_LINE(The department exist!);
  else
    DBMS_OUTPUT.PUT_LINE(The department not exist!);
  end if;
END;
/

练习 6:创建增加雇员的过程

CREATE OR REPLACE PROCEDURE new_emp
    (v_ename   emp.ename%TYPE,
     v_job     emp.job%TYPE     DEFAULT SALESMAN,
     v_mgr     emp.mgr%TYPE     DEFAULT 7839,
     v_sal     emp.sal%TYPE     DEFAULT 1000,
     v_comm    emp.comm%TYPE    DEFAULT 0,
     v_deptno  emp.deptno%TYPE  DEFAULT 30)
IS
V_FLAG BOOLEAN;
BEGIN
    valid_deptno(v_deptno,V_FLAG);
    IF V_FLAG THEN
      INSERT INTO emp
      VALUES (seq_empno.NEXTVAL, v_ename, v_job, v_mgr, 
              TRUNC (SYSDATE, DD), v_sal, v_comm, v_deptno);
    ELSE
      DBMS_OUTPUT.PUT_LINE(Invalid Deptno ,try again!);
    END IF;
END new_emp;
/

练习 7:分页查询

create or replace procedure TABLEPAGE_SELECT
 (v_page_size number,v_current_page number)
as
cursor c(v_page_size number,v_current_page number) is SELECT *
            FROM (select rownum rn,emp.*
                  FROM emp WHERE rownum <= v_page_size*v_current_page)
            WHERE rn >= (v_page_size*v_current_page-(v_page_size-1));
begin
  dbms_output.put_line(pagesize : ||v_page_size|| rows);
  dbms_output.put_line(current page : ||v_current_page|| page);
  for r in c(v_page_size,v_current_page) loop
      dbms_output.put_line(employee name : ||r.ename|| employee‘‘s salary : ||r.sal);
  end loop;
end;
/

存储过程的调用:
exec TABLEPAGE_SELECT(5,2);

练习 8:本地动态SQL语句(execute immediate) 

create or replace procedure proc_test
(
  table_name in varchar2,   --表名
  field1 in varchar2,     --字段名
  datatype1 in varchar2,   --字段类型
  field2 in varchar2,     --字段名
  datatype2 in varchar2    --字段类型
) as 
  str_sql varchar2(500);
begin 
  str_sql:=create table ||table_name||(||field1|| ||datatype1||,||field2|| ||datatype2||);
  execute immediate str_sql;  --动态执行DDL语句
  exception 
    when others then 
      null;
end ;
/

给动态语句传值(USING 子句)

declare
   l_depnam varchar2(20) := testing;
   l_loc     varchar2(10) := Dubai;
begin
   execute immediate insert into dept values   (:1, :2, :3)
     using 50, l_depnam, l_loc;
   commit;
end;

为procedure加密(Wrap加密)

用法:

wrap的用法还是比较简单的,一个命令就可以实现加密,以下是命令的格式:

wrap iname=input_file [ oname=output_file ]

iname:指定的是源文件

oname:指定的是转换后加密文件,oname选项可以省略如果省略wrap命令会自动生成文件名一模一样的加密文件,后缀为.plb,当然你也可以指定自己命名方式。

执行编译方法:在SQLplus环境执行 @output_file.plb

注:目前该加密方式已经被破译。