6.Procedure存储过程
语法:
CREATE OR REPLACE PROCEDURE procedure_name
[(argument_name [{IN|OUT|IN OUT}] TYPE,
...
argument_name [{IN|OUT|IN OUT}] TYPE)]
{IS|AS}
BEGIN
statements
END;
存储过程也称作:带名块,它可存储于数据库中,可以在任何需要的地方调用,此外带明块还包括: FUNCTION,PACKAGE,TRIGGER.
有带名的,当然周有不带名的:匿名块
匿名块:
不能存储在数据库中,每次使用时都进行解析,不能在其他块中相互调用
语法:
DECLARE
//声明取
BEGIN
//块体
END
继续回到Procedure,先看一个简单的demo:
CREATE OR REPLACE PROCEDURE pro_hello IS
//以上头部相当于匿名块的:DECLARE
BEGIN
DBMS_OUTPUT.PUT_LINE('HELLO,WORLD');
//在屏幕上输出一个HELLO,WORLD字符串,每进入一次SQLPLUS时,程序中要想看到输出结果就要打开开关:set serveroutput on
END;
可以在匿名块中调用上面的存储过程,
BEGIN
pro_hello;
//存储过程的名字
END;
以上是一个简单的示例!没么实用价值,通常我们用数据库都会涉及对数据的:增,删,改,查:
超简单的查询:
CREATE OR REPLACE PROCEDURE pro_lab(
p_id s_emp.ID%TYPE //p_id是pro_lab的形参
) IS
v_fname s_emp.FIRST_NAME%TYPE;
BEGIN
SELECT FIRST_NAME
INTO v_fname
//INTO把查的结果赋值给变量:v_fname
FROM s_emp
WHERE ID=p_id;
DBMS_OUTPUT.PUT_LINE('HELLO, '||v_fname);
END;
//调用procedure
file-name:lab1.sql
BEGIN
pro_lab(1); //1:pro_lab的实参
END;
Procedure的参数模式:
IN:
默认模式.在调用Procedure的时候,Procedure的实参的值被传递到该Procedure,在Procedure的内部,Procedure的形参是只读的:
OUT:
在调用Procedure时,任何的Procedure的实参都将被忽略,在Procedure的内部,形参是只可写的:
IN OUT:
IN与OUT的组合.在调用Procedure的时候,实参的值可以被传递给该Procedure;在其内部,形参也可以被读出也可以被写入;该Procedure结束时,控制会返回给控制环境,而形参的内容将赋给调用时的实参.
CREATE OR REPLACE PROCEDURE pro_param(
p_in IN NUMBER, //参数类型后不能带精度/刻度,也周是不能带:(3)
p_out OUT NUMBER //procedure的形参
) IS
BEGIN
DBMS_OUTPUT.PUT_LINE('IN PARAM: '||p_in);
p_in := 100; //IN模式的形参只可读
DBMS_OUTPUT.PUT_LINE('OUT PARAM: '||p_out);
p_out : = 200; //OUT模式只能从procedure往外带值
END;
//调用procedure
file-name:lab3.sql
DECLARE
v_out NUMBER :=100; //该实参不能传进procedure中
BEGIN
pro_param(2,v_out); //2:IN 模式的实参 v_out:OUT模式的实参
END;
练习:
查询某位员工的领导姓名
CREATE OR REPLACE PROCEDURE p_lab(
p_id IN s_emp.ID%TYPE,
p_fname OUT s_emp.FIRST_NAME%TYPE) IS
v_fname s_emp.FIRST_NAME%TYPE;
v_mid s_emp.ID%TYPE;
BEGIN
SELECT decode(a.FIRST_NAME, NULL, b.FIRST_NAME, a.FIRST_NAME) name
INTO v_fname
FROM s_emp a,s_emp b
WHERE b.MANAGER_ID=a.ID(+) and b.ID=p_id;
p_fname := v_fname;
/*
SELECT FIRST_NAME,MANAGER_ID
INTO v_fname,v_mid
FROM s_emp
WHERE ID=p_id
IF v_mid IS NULL THEN
p_fname := v_fname;
ELSE
SELECT FIRST_NAME
INTO p_fname
FROM s_emp
WHERE ID=v_mid
END IF
*/
END;
file-name:lab6.sql
DECLARE
v_name s_emp.FIRST_NAME%TYPE;
BEGIN
p_lab(3,v_name);
DBMS_OUTPUT.PUT_LINE('MANAGER IS: '||vname);
END;
注惜掉的是老师推荐的写法