开发笔记_Oracle学习笔记 _12_PL/SQL(过程 & 块)

Oracle学习 第12天

            —— PL/SQL 编程(过程 & 块)

                PL/SQL (Procedural Language/SQL) 是 Oracle 在标准的 SQL 语言上的扩展,PL/SQL 不仅允许嵌入SQL语言,还可以定义变量和常量,可以使用条件语句、循环语句,允许使用例外处理错误。其功能十分强大,有点类似于某种后台语言(JAVA、C++、C#等)与SQL语句的结合形式。

                PL/SQL是一种 语言,而SQL只是一种 语句

                SQL语句直接操作的几大缺陷:
                        1、无法进行模块化编程。只能单条的去执行,即使是事务,也是单条执行完成后一起提交而已。
                        2、执行速度慢。SQL语句写在编程语言中,被编程语言的编译机制编译之后,发送给DBMS,DBMS又需要重新将被编程机制编译后的SQL语句重新编译为Oracle认识的SQL语句,然后才可以执行。多次编译浪费了大量时间。
                        3、安全隐患。在使用SQL语句编程的同时,不可避免的需要写入需要操作的列名、表名等一部分数据。这些数据虽然表面上看似不是很重要,但对于专业人士来讲,这些数据的暴露也是很危险的。
                        4、浪费带宽。与执行速度的分析类似,多次的数据传输同样会浪费大量的带宽。

                PL/SQL编程的优缺点:
                优点:
                        1、提高应用程序的运行性能;
                        2、模块化的设计思想(分页的过程、订单的过程、转账的过程等。类似将SQL封装为函数的思想);
                        3、减少网络传输量;
                        4、提高安全性;
                 缺点:
                        1、移植性差。即不同的数据库平台之间的PL/SQL代码是不通用的。


过程的概念

                了解了PL/SQL编程之后。我们再引入一个概念—— 过程
                过程及存储过程。即用来完成一个特定操作的一组SQL语句的 集合。      --  模块化编程
                其整体概念有点类似于函数。当用户需要使用时, 直接调用过程即可。  --  执行速度提升
                过程是经过编译之后存储在数据库中的 二进制文件。                             --  安全性提升
创建存储过程(一)
基本语法:
CREATE [OR REPLACE] PROCEDURE 过程名(参数1 参数类型, 参数2 参数类型, ……)
IS            --或者AS
初始化变量;
BEGIN
    执行SQL语句;
END;
/

★:注意:

        1、过程参数的定义方式与函数参数定义的方式不同。过程的参数定义是参数名在前,参数类型在后。

        2、上述基本语法中 斜杠/ 的意义。

              因为在脚本中,可能存在多条SQL语句,如果没有斜杠,则遇到分号就会执行,而在脚本定义中,不需要马上执行。

              该符号多用于创建创建存储过程,其意义为:执行之前的SQL脚本。  

              在PL/SQL等客户端中,可以使用执行选中代码,就不必使用/。

        3、IS 与 BEGIN 关键字之间的部分,仅仅用于声明变量,可以初始化,但不允许赋值;

        4、传入的输入参数不允许作为赋值目标;

示例1(IS 与 BEGIN 之间可以声明变量)

SQL> CREATE OR REPLACE PROCEDURE pro_test(v_empno NUMBER)
  2  IS
  3  v_sal NUMBER;  -- 定义变量
  4  BEGIN
  5    SELECT sal INTO v_sal FROM emp WHERE empno = v_empno;
  6  END;
  7  
  8  /

Procedure created

示例2(IS 与 BEGIN 之间可以声明并初始化变量

SQL> CREATE OR REPLACE PROCEDURE pro_test(v_empno NUMBER)
  2  IS
  3  v_sal NUMBER := 100;  -- 定义变量 并初始化
  4  BEGIN
  5    SELECT sal INTO v_sal FROM emp WHERE empno = v_empno;
  6  END;
  7  /

Procedure created
示例3( IS 与 BEGIN 之间不可以对变量进行赋值
SQL> CREATE OR REPLACE PROCEDURE pro_test(v_empno NUMBER)
  2  IS
  3  v_sal NUMBER;  -- 定义变量
  4  v_sal := 100;  -- 对变量赋值
  5  BEGIN
  6    SELECT sal INTO v_sal FROM emp WHERE empno = v_empno;
  7  END;
  8  /

Warning: Procedure created with compilation errors


SQL> show error
Errors for PROCEDURE SCOTT.PRO_TEST:
LINE/COL ERROR
-------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4/7      PLS-00103: 出现符号 "="在需要下列之一时:   constant exception     <an identifier> <a double-quoted delimited-identifier> table     long double ref char time timestamp interval date binary     national character nchar  符号 "<an identifier>" 被替换为 "=" 后继续。  

SQL> 

示例4:-- 创建一个过程,其功能是删除EMP表中EMPNO为‘1234’的用户。

SELECT * FROM emp;

CREATE [OR REPLACE] PROCEDURE pro_test(eno VARCHAR2)        -- CREATE OR REPLACE : 如果该过程不存在则创建,如果存在则更新替换
IS
BEGIN
  DELETE FROM emp WHERE empno=eno;
END;

SELECT * FROM emp;


调用存储过程
基本语法:
                以下两种语句都可以调用过程
EXEC 过程名(参数1, 参数2, ……);
CALL 过程名(参数1, 参数2, ……);

★:注意:在命令行中,可以直接使用EXEC调用存储过程。

                但是在 PL/SQL 客户端中。SQL WINDOWS 窗口是无法直接执行EXEC命令的(会报错:无效的SQL命令)

                需要在COMMAND WINDOW窗口下执行。


SELECT * FROM EMP;

▲ :说明:在COMMAND 窗口编写过程时,如果遇到报错,默认是不会显示错误内容的。

                 可以使用 SHOW ERROR 命令来查询具体报错内容。


创建存储过程(二)

                建立存储过程时,还可以直接明确指定输入参数(IN)或者输出参数(OUT)。

                输入参数可以将数据传递到执行部分。

                输出参数可以将数据传递到应用的环境。

基本语法:

CREATE [OR REPLACE] PROCEDURE 过程名(变量 IN 变量类型……, 变量 OUT 变量类型) IS
BEGIN
执行语句;
END;
/
★ 注意:在不明确指定 IN 或 OUT 时,默认的是输入参数,即 IN 。


JAVA中调用存储过程
 我们先创建一个存储过程 PRO_TEST 用来向 EMP 表中插入一条记录。
SQL> create or replace procedure pro_test(v_empno IN number, v_name IN varchar2, v_sal number) IS
  2  begin
  3  insert into emp(empno, ename, sal) values(v_empno, v_name, v_sal);
  4  end;
  5  /

Procedure created
SQL> commit;            -- 一定要记得提交,否则事务目前被 COMMAND 窗口占用, java 代码是无法执行的
Commit complete

编写JAVA程序调用该存储过程。
public class TestProcedure {
	public static void main(String[] args) {
		Connection ct = null;
		CallableStatement  cs = null;
		try {
			// 加载驱动
			Class.forName("oracle.jdbc.driver.OracleDriver");
			//得到连接
			ct = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:ORCL", "scott", "scott");
			/* sql 语句 固定写法 :
			 * 大括号{}包含
			 * 
			 * 			{call 过程名(占位符, 占位符, ……)}
			 * 
			 * ?为占位符,需要传几个参数就写几个问号		★ 这里的参数指 IN 参数。 OUT 参数 一会儿另行演示
			 * */
			String sql = "{call pro_test(?,?,?)}";
			// 创建 CallableStatement 接口引用对象
			cs = ct.prepareCall(sql);
			//对占位符 ? 赋值    注意:?的个数是从 1 开始计数
			cs.setInt(1, 7777);			// 第一个?赋值 7777
			cs.setString(2, "jack");	// 第二个?赋值jack
			cs.setFloat(3, 4000.89F);	// 第三个?赋值Float类型的 4000.89
			//执行  execute 方法用来执行任何种类的 SQL 语句 ,返回一个 boolean 类型
			cs.execute();
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		} finally {
			//关闭资源 (本例省略)
		}
	}
}


PL/SQL编程规范


                1、单行注释:    -- 内容

                2、多行注释:    /* 内容 */

                3、变量:           v_  作为前缀。如 v_name

                4、常量:           c_  作为前缀。如 c_class

                5、游标:           _cursor 作为后缀。 如 student_cursor

                6、例外:           e_  作为前缀。 如 e_error

块(Block)

                块是PL/SQL的基本程序单元。编写PL/SQL程序实际上就是编写PL/SQL块。

                可以在一个PL/SQL块中嵌套其他的PL/SQL块来实现一些复杂的功能。


                块的意义类似于其他编程语言中的类(class)。但是写法有很大的不同。

                首先,块中的定义与执行是完全分开的,这与其他编程语言的类中可以随时定义变量的写法完全不同。


                块 由三部分构成:定义部分、执行部分、例外部分。其结构非常严格。

                块的基本结构如下:

/*定义部分(可选) -- 定义常量、变量、游标、其他数据类型等*/
DECLARE

/*执行部分(必须) -- 要执行的SQL语句或PL/SQL语句*/
BEGIN

/*例外部分(可选) -- 处理运行时可能产生的各种错误*/
EXCEPTION

END; -- 结束标志
                Oracle中, 也提供了很多的常用开发包(基本上都是以 dbms_ 为前缀)。其中包含了一些过程。

示例1:

                -- 在PL/SQL客户端的Command Window下打印输出 Hello World

SQL> /
SQL> set serveroutput on;                -- ★ 默认打印台是关闭的,我们需要先设置打开。后面的实例省略该步骤
SQL> /
SQL> begin
  2  dbms_output.put_line('Hello World!');
  3  end;
  4  /

Hello World!

PL/SQL procedure successfully completed

示例2:

                -- 查询emp表中编号为7900的员工姓名,并将姓名赋值给一个变量。

                块的写法如下:

SQL> declare                            -- 声明变量的关键字
  2  v_name varchar2(20);               -- 变量名 变量类型  ★ 这里不仅需要指定类型,还需要指定长度。
  3  begin                              -- 执行体开始
  4  select ename into v_name from emp where empno = &empno;    
                                        -- 此处 &empno 的写法 会弹出窗口要求用户输入 empno 的值
                                        -- 从 emp 表中 查询 enamel 字段  赋值给 v_name 变量 。查询条件为 empno = 弹出对话框后用户输入的值
  5  dbms_output.put_line('The name is '||v_name);
                                        -- 输出 The name is 变量v_name的值
  6  end;                               -- 执行体结束
  7  /                                  -- 执行上面脚本

The name is JAMES

PL/SQL procedure successfully completed
                过程的写法如下:

SQL> create procedure pro_test(in_empno number)
  2  IS
  3  v_name varchar2(20);
  4  BEGIN
  5  select ename into v_name from emp where empno = in_empno;
  6  dbms_output.put_line('The name is '||v_name);
  7  end;
  8  /

Procedure created

SQL> exec pro_test(7900);

The name is JAMES

PL/SQL procedure successfully completed

★ 注意:

                在定义块时,变量不仅仅需要指定类型,还需要指定长度;

                在定义过程时,参数只需要指定类型,不需要指定长度;

示例3:

                -- 查询emp表中编号为1234的员工姓名,实际上该员工并不存在,我们需要让他执行异常处理。

SQL> declare
  2  v_name varchar2(20);
  3  begin
  4  select ename into v_name from emp where empno = &empno;
  5  end;
  6  /
declare
v_name varchar2(20);
begin
select ename into v_name from emp where empno = 1234;
end;

ORA-01403: 未找到任何数据
ORA-06512: 在 line 4

可以看出,Oracle中默认的有提供一些异常处理机制,在没有找到数据时会有“ORA-01403:未找到数据”提示。

但是,这对于普通的用户来说,并不是所有的Oracle提示都能看的懂,所以,我们需要尝试着让Oracle在发生异常时,执行我们自己定义的语句。

异常部分的基本语法:

EXCEPTION
WHEN 异常名称 THEN 
执行代码;
WHEN 异常名称2 THEN
执行代码2;

SQL> declare
  2  v_name varchar2(20);
  3  begin
  4  select ename into v_name from emp where empno = &empno;
  5  dbms_output.put_line('员工姓名:'||v_name);
  6  exception
  7  when no_data_found then
  8  dbms_output.put_line('没有找到数据,您输入的员工号可能有误');
  9  end;
 10  /

没有找到数据,您输入的员工号可能有误

PL/SQL procedure successfully completed

示例中异常的处理代码仅仅是打印了自定义的一句话。

当然也可以写其他的执行语句,比如:如果没有找到该员工,就新增一条信息?  

同样是可以的。只需要在第8行后加入 INSERT INTO 的SQL语句即可。




猜你喜欢

转载自blog.csdn.net/shaotaiban1097/article/details/80550465