plsql块
plsql的块总共有两种类型:匿名块(没有名字的块)和命名块,匿名块具有有限的作用域(功能较少),命名块更容易扩展,而且可重用资源。
匿名块功能可使用在:脚本或其他的程序单元中,也就是说匿名块的作用域仅限于包含匿名块的程序单元或脚本。
命名块程序作为函数或者过程直接保存在模式中,命名快的作用最为灵活。其次可以将命名块程序保存在包里面,一种方法通过发布包函数或者过程。一种方法是独占的将函数或者过程保存在包主体内,这种方法限制此程序只能在包内部使用。
匿名块
匿名块原型:
DECLARE (可选)
Variables(变量), cursors(游标), user-defined exceptions(异常)
BEGIN (程序执行部分,也就是业务开始)
SQL 语句
PL/SQL 语句
EXCEPTION (可选)
处理异常
END; (程序块结束)
最佳操作:
在实现任何的局部命名块之前,记住为其定义前向引用规范,确保局部命名块能够相互调用
有两个小小的细节,第一个是作为一个强逻辑块的语言,它要求在每一个块中至少包括一条语句。第二个细节是
sql*plus格式化环境变量serveroutput来管理plsql程序的输出。
对于第一个细节plsql提供null语句,在块中使用null语句,可以在编写详细的块逻辑之前确保基本块逻辑控制正确。
BEGIN
NULL;--没有任何语句的时候记得赋值null可以为自己解决很多的麻烦
END;
对于第一个细节如果使用命令行方式编程则需要配置环境变量,下面是命令行方式图
set serveroutput on--输出
命令行方式写匿名块:
注意:q'()'可以替代引号在程序中使用,但是个人觉得还是用引号比较方便
替代变量
使用替代变量,可以将输入的参数分配给匿名块程序。使用&符号作为前缀,替代变量可以是可变长得字符串或者是数字,不能再声明块中分配动态值。
DECLARE
v_num1 VARCHAR2(30);--变量
v_num2 VARCHAR2(30);--变量
BEGIN
v_num1 :='&a';--从键盘输入,但是我不太明白为什么用引号
/* 测试结果输入你好,输出你好,解释了为什么带引号*/
v_num2:=&a;
/* 测试结果输入你好,出错必须带字符串*/
dbms_output.put_line(v_num1);
dbms_output.put_line(v_num2);
END;
建议:始终在执行块中进行赋值或初始化,除非局部变量是常量或被视为常量,这样可以消除许多运行时赋值错误。
DECLARE
v_num CONSTANT VARCHAR2(25) := '挣大钱'; --定义一个常量
BEGIN
--打印输出常量,常量在业务中是不变的,不能再业务中再改变它的值
dbms_output.put_line(v_num);
END;
可绑定变量
这困扰了我一下,课件上面的代码运行不了,很懵逼。
处理交互式会话级变量的另一种方法是使用一种特殊的变量,oracle称为绑定(bind)变量,绑定变量使用冒号:作为前缀。
注意:不应该在声明块中对绑定变量赋值。
plsql命令行下运行
--会话级绑定变量,会话中变量的定义不适用冒号作为前缀,plsql块中使用冒号作为前缀
VARIABLE b VARCHAR2(20);--可绑定变量b
BEGIN
:b:='挣大钱';
END;
使用绑定变量(关闭一个窗口也就是一个会话肯定是不能获取到值了,因为你本次的会话已经关闭了,没有可绑定的变量)
DECLARE
v_num VARCHAR2(20);
BEGIN
v_num :=:b;--使用绑定变量
dbms_output.put_line(v_num);
END;
运行脚本
当时我建表的时候也出现问题,因为日期插入有错,明明表是老师给的为什么运行不了呢?于是百度了一下可以使用脚本的方式运行,
方法是:
也就是在sw下编写代码,保存然后使用cw来运行(@D:\自己打的代码的脚本文件\调用可绑定变量.sql)
命名块
我们知道可以运行匿名块如何完成我们想要的功能,但是命名块的功能更强大,存储程序提供了和匿名块相同的功能,但是可以将其部署到数据库中,并从数据库重用这些存储程序。(推荐使用存储程序)
过程块
过程在另一个程序的作用域内运行,并执行某项任务。一般,开发人员调用过程,在某个现有事务作用域内执行任务如插入或更新表。
--注意的in可以省略不写,过程是没有返回值的,可以使用
--dbms_output.put_line()输出
CREATE OR REPLACE PROCEDURE h1(p_num IN VARCHAR2
) IS
BEGIN
dbms_output.put_line('挣大钱');
END h1;
运行(调用过程):
BEGIN
h1('你要');
END;
函数块
函数总而言之有返回值,必须含有return语句
CREATE OR REPLACE FUNCTION t1(p_num varchar2--输入的参数
) RETURN VARCHAR2 IS
v_num1 VARCHAR2(35);--输出的变量
BEGIN
v_num1 :=p_num||'挣大钱';--使用到字符拼接
RETURN(v_num1);--函数必须有返回值
END t1;
调用函数
BEGIN
dbms_output.put_line(t1('我要'));
END;
嵌套块
命名块还可以嵌套在其他命名块或匿名块中,那么问题来了,嵌套命名块并不是已经发布的,这意味着在调用一个命名块时,被调用的命名块可能还没有定义。这种类型的设计也称为‘作用域错误’,被调用的程序在调用发生之前是未知的。导致编译错误。
解决方法一:被调用的命名块放在前面。
DECLARE
--被调用的要放在前面
FUNCTION b RETURN VARCHAR2 IS
BEGIN
RETURN 'hello';
END b;
--调用者放在后面
procedure a IS
BEGIN
dbms_output.put_line(b||'挣大钱');
END a;
BEGIN
a;--调用程序a
END;
解决方法二:为过程和函数提供占位程序
DECLARE
--定义
PROCEDURE a;--存储过程
FUNCTION b RETURN VARCHAR2;--函数
PROCEDURE a IS
BEGIN
dbms_output.put_line(b||'挣大钱');--调用b程序过程
END a;
FUNCTION b RETURN VARCHAR2 IS
BEGIN
RETURN '我要';
END b;
BEGIN
a;--调用a的程序过程
END;