使用 Oracle PL/SQL NOCOPY 提示
参考文献:
official document: http://docs.oracle.com/cd/B19306_01/appdev.102/b14261/tuning.htm#LNPLS01208
oracle nocopy hint tips: http://www.dba-oracle.com/plsql/t_plsql_nocopy_hint.htm
http://www.dba-oracle.com/t_pl_sql_nocopy_data_structures.htm
一 概念介绍:
PLSQL运行引擎在存储过程和函数之间传参有2种方法:传值和传引用
默认情况,OUT和IN OUT参数通过传值方式传递,IN参数是传引用方式。程序执行前IN OUT参数的实际值将被复制给形参。程序执行中间,临时变量保存参数的输出值。如果程序正常退出,这些值将被复制回原参数。如果程序异常退出,那么原参数值将不会改变。当IN OUT参数为大数据结构,诸如:集合、记录、对象类型实例时,通过传值方式的COPY动作将会导致程序执行速度下降,使用内存量上升。尤其是该程序被多次调用时更是如此。
为避免此类情况,我们可以指定NOCOPY暗示,告诉PLSQL编译器通过传引用方式传递OUT 和IN OUT参数。这样,形参将不会COPY参数实际值,也就是说形参和ACTUAL VALUE指向同一内存地址(memory location)。以此提高程序执行性能。
下面通过一段脚本对比一下,传值和传引用在程序执行性能上的差异:
二 示例对比:
nocopy.sql
SET SERVEROUTPUT ON
DECLARE
TYPE t_tab IS TABLE OF VARCHAR2(32767);
l_tab t_tab := t_tab();
l_start NUMBER;
PROCEDURE in_out (p_tab IN OUT t_tab) IS
BEGIN
NULL;
END;
PROCEDURE in_out_nocopy (p_tab IN OUT NOCOPY t_tab) IS
BEGIN
NULL;
END;
BEGIN
l_tab.extend;
l_tab(1) := '1234567890123456789012345678901234567890';
l_tab.extend(999999, 1); -- Copy element 1 into 2..1000000
-- Time normal IN OUT
l_start := DBMS_UTILITY.get_time;
in_out(l_tab);
DBMS_OUTPUT.put_line('IN OUT : ' ||
(DBMS_UTILITY.get_time - l_start));
-- Time IN OUT NOCOPY
l_start := DBMS_UTILITY.get_time;
in_out_nocopy(l_tab); -- pass IN OUT NOCOPY parameter
DBMS_OUTPUT.put_line('IN OUT NOCOPY: ' ||
(DBMS_UTILITY.get_time - l_start));
END;
/
SQL> @nocopy.sql
IN OUT :43
IN OUT NOCOPY: 0
PL/SQL procedure successfully completed.
三 使用NOCOPY限制:
1、如果实参为整个关联数组则该限制不起作用。
2、实参被强制指定精度,比例或not null时,该限制将不适用按最大长度强制的字符串参数。
3、实参和形参都是记录类型,二者存在以隐式方式或使用了%ROWTYPE类型声明时,作用在对应字段的强制说明不一制。
4、传递实参需要隐式类型转换时。
5、子程序涉及到远程调用(RPC---database link oras an external procedure)。
四 关于使用NOCOPY过程中的异常处理
虽说NOCOPY带来了性能上的优势,但是不容忽略的一点是当我们调用的子程序(带有NOCOPY提示)发生异常时,一旦处理不当很容易造成实参被修改。这是我们不愿看到的。下面引用官方的一段话并结合newkid大师的例子给予说明,详细请见ITPUB版:
http://www.itpub.net/thread-1147041-1-1.html
If the subprogram exits early with an exception, the values of OUT and IN OUT parameters (or object attributes) might still change. To use this technique, ensure that the subprogram handles all exceptions.
CREATE OR REPLACE PROCEDURE p_nocopy_test(p_id OUT NOCOPY NUMBER)
AS
BEGIN
p_id := 1;
raise_application_error(-20201,'NULL'); --程序终止
p_id := 2;
RETURN;
END;
/
DECLARE
v_id NUMBER := 0;
BEGIN
dbms_output.put_line('Before call p_nocopy_test: '||v_id);
p_nocopy_test(v_id);
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('After call p_nocopy_test: '||v_id);
END;
/
Before call p_nocopy_test: 0
After call p_nocopy_test: 1
再来看一下去掉NOCOPY参数的子程序调用在遇到异常时的表现:
Before call p_nocopy_test: 0
After call p_nocopy_test: 0
那么针对NOCOPY子程序的异常处理该如何做?Oracle前面说了应该在子程序内部捕捉处理掉异常,例如:
CREATE OR REPLACE PROCEDURE p_nocopy_test(p_id OUT NOCOPY NUMBER)
AS
BEGIN
p_id := 1;
raise_application_error(-20201,'NULL'); --程序终止
p_id := 2;
--RETURN;
EXCEPTION
WHEN OTHERS THEN
p_id := 0;
RETURN;
END;
/
DECLARE
v_id NUMBER := 0;
BEGIN
dbms_output.put_line('Before call p_nocopy_test: '||v_id);
p_nocopy_test(v_id);
/*
EXCEPTION
WHEN OTHERS THEN
*/
dbms_output.put_line('After call p_nocopy_test: '||v_id);
END;
/
Before call p_nocopy_test: 0
After call p_nocopy_test: 0
-------------------
Dylan presents.
使用 Oracle PL/SQL NOCOPY 提示的更多相关文章
- ORACLE PL/SQL编程详解
ORACLE PL/SQL编程详解 编程详解 SQL语言只是访问.操作数据库的语言,并不是一种具有流程控制的程序设计语言,而只有程序设计语言才能用于应用软件的开发.PL /SQL是一种高级数据库程序设 ...
- [推荐]ORACLE PL/SQL编程之五:异常错误处理(知已知彼、百战不殆)
原文:[推荐]ORACLE PL/SQL编程之五:异常错误处理(知已知彼.百战不殆) [推荐]ORACLE PL/SQL编程之五: 异常错误处理(知已知彼.百战不殆) 继上三篇:ORACLE PL/S ...
- ORACLE PL/SQL编程之六:把过程与函数说透(穷追猛打,把根儿都拔起!)
原文:ORACLE PL/SQL编程之六:把过程与函数说透(穷追猛打,把根儿都拔起!) ORACLE PL/SQL编程之六: 把过程与函数说透(穷追猛打,把根儿都拔起!) 继上篇:ORACLE P ...
- [推荐]ORACLE PL/SQL编程详解之三:PL/SQL流程控制语句(不给规则,不成方圆)
原文:[推荐]ORACLE PL/SQL编程详解之三:PL/SQL流程控制语句(不给规则,不成方圆) [推荐]ORACLE PL/SQL编程详解之三: PL/SQL流程控制语句(不给规则,不成方圆) ...
- [推荐]ORACLE PL/SQL编程详解之一:PL/SQL 程序设计简介(千里之行,始于足下)
原文:[推荐]ORACLE PL/SQL编程详解之一:PL/SQL 程序设计简介(千里之行,始于足下) [推荐]ORACLE PL/SQL编程详解之一: PL/SQL 程序设计简介(千里之行,始于足下 ...
- [顶]ORACLE PL/SQL编程详解之二:PL/SQL块结构和组成元素(为山九仞,岂一日之功)
原文:[顶]ORACLE PL/SQL编程详解之二:PL/SQL块结构和组成元素(为山九仞,岂一日之功) [顶]ORACLE PL/SQL编程详解之二: PL/SQL块结构和组成元素(为山九仞,岂一日 ...
- Oracle PL/SQL Articles
我是搬运工....http://www.oracle-base.com/articles/plsql/articles-plsql.php Oracle 8i Oracle 9i Oracle 10g ...
- ORACLE PL/SQL编程详解(转)
原帖地址:http://blog.csdn.net/chenjinping123/article/details/8737604 ORACLE PL/SQL编程详解 SQL语言只是访问.操作数据库的语 ...
- Oracle PL/SQL Developer 上传下载Excel
接到需求,Oracle数据库对Excel数据进行上传和下载,百度后没有很全的方案,整理搜到的资料,以备不时之需. 一.下载Oracle数据到Excel中. 下载数据到Excel在MSSql中很简单,直 ...
- [强烈推荐]ORACLE PL/SQL编程详解之七:程序包的创建与应用(聪明在于学习,天才在于积累!)
原文:[强烈推荐]ORACLE PL/SQL编程详解之七:程序包的创建与应用(聪明在于学习,天才在于积累!) [强烈推荐]ORACLE PL/SQL编程详解之七: 程序包的创建与应用(聪明在于学习,天 ...
随机推荐
- C++11 同步与互斥
C++11 同步与互斥 0. C++11的线程 #include <thread> 面向对象的接口 RAII(资源获取即初始化)机制,当线程对象被销毁时,会自动执行析构函数,如果线程仍然在 ...
- Linux-文件压缩-tar-gzip
- [转帖]命令行参数--与-D的区别
https://juejin.cn/post/7238420276228341815 Spring Boot 学习笔记 我们要想了解这两者之间的差异,首先来看一个案例: bash 复制代码 # ...
- [转帖]ARM内核全解析,从ARM7,ARM9到Cortex-A7,A8,A9,A12,A15到Cortex-A53,A57
https://www.cnblogs.com/senior-engineer/p/8668723.html 前不久ARM正式宣布推出新款ARMv8架构的Cortex-A50处理器系列产品,以此来扩大 ...
- [转帖]Oracle JDBC中的语句缓存
老熊 Oracle性能优化 2013-09-13 在Oracle数据库中,SQL解析有几种: 硬解析,过多的硬解析在系统中产生shared pool latch和library cache liatc ...
- [转帖]ls 只显示目录
https://www.cnblogs.com/lavin/p/5912369.html 只显示目录: ls -d */ 在实际应用中,我们有时需要仅列出目录,下面是 4 种不同的方法. 1. 利用 ...
- [转帖]Promethues + Grafana + AlertManager使用总结
Prometheus是一个开源监控报警系统和时序列数据库,通常会使用Grafana来美化数据展示. 1|01. 监控系统基础架 1|11.1核心组件 Prometheus Server, 主要用于抓取 ...
- [转帖] Linux命令拾遗-常用的辅助开发类命令
https://www.cnblogs.com/codelogs/p/16060735.html 原创:打码日记(微信公众号ID:codelogs),欢迎分享,转载请保留出处. 简介# 之前介绍了大量 ...
- Redis7.0.7的简单安装与学习
Redis7.0.7的简单安装与学习 摘要 2022.12.18 世界杯决赛 另外是我感染奥密克戎第五天. 高烧已经没了,但是嗓子巨疼. 睡不着觉,肝胆学习一下最新的Redis7.0.7 第一部分安装 ...
- 解决Word等打开嵌入的文件提示 包含有害内容 无法打开的问题
最近打开文件时提示: 从网上找了一下 最简单的解决办法是: 新建一个文件, 输入如下内容 导入注册表 每次打开时不进行 文件有效性的检查即可. 为了省事 我多加了几个版本的 如果是excel 将 w ...