PL/SQL批处理语句:BULK COLLECT 和 FORALL对优化的贡献
我们知道PL/SQL程序中运行SQL语句是存在开销的,因为SQL语句是要提交给SQL引擎处理 这种在PL/SQL引擎和SQL引擎之间的控制转移叫做上下文却换,每次却换时,都有额外的开销 请看下图: 但是,FORALL和BULK COLLECT可以让PL/SQL引擎把多个上下文却换压缩成一个,这使得在PL/SQL中的要处
存储过程的运用之print_table
create or replace procedure print_table ( p_query in varchar2, p_date_fmt in varchar2 default \'dd-mon-yyyy hh24:mi:ss\' ) -- this utility is designed to be installed ONCE in a database and used -- by all. Also, it is nice to have roles enabled so that queries by -- DBA\'s that use a role to gain access to the DBA_* views still work -- that is the purpose of AUTHID C
切莫硬编码VARCHAR2长度
看个例子先,DECLARE think_big VARCHAR2(2000); 不看不知道,一看吓一跳呀,这容器够大也够辣,啥俺们都能吞进去,绝不挑食 然而,这绝对是一颗定时炸弹 Oracle 8时代,VARCHAR2的最大长度是2000 Oracle 8i之后,变成了4000, 为了向后兼容,还会变成啥哩?who knows?
捕获声明部分的异常
异常捕获作用于执行部分,而在声明部分抛出的异常是无法被捕获的 比如,DECLARE var_id number :=\'Think\'; BEGIN NULL; EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE(\'Exception captured\'); END; 处理的方法,其实也很简单,就是在外面套一层,天凉了,多件外套哟~BEGIN DECLARE var_id number :=\'Think\'; BEGIN NULL; EXCEPTION
SUBTYPE正规化数据类型
SUBTYPE是类型的别名,倘若需求变更,只需修改一个地方的定义,其他代码都不用改动 也许我们习惯了变量来代表未知数,但却不习惯变量来代表变量类型 而subtype正是起到了这样的作用,他可以用一个新的类型变量来代表一个已知的类型 如果你定义的变量很可能需要改变变量类型,则使用subtype能
触发器内的代码封装
实验准备:hr@ORCL> drop table t purge; Table dropped. hr@ORCL> create table t (code number); Table created. hr@ORCL> create table t_audit (code number,ins_date date); Table created. hr@ORCL> create or replace trigger tri_audit_t 2 before insert 3 on t 4 for each row 5 begin 6 insert into t_audit values(:new.code,sysdate); 7 end; 8 / 同时打开两个session,
INSTEAD OF 触发器的使用陷阱
对于两张表以上关联起来的视图,Oracle是分不出来应该对哪个表进行更新 而INSTEAD OF 触发器实现了我们对视图DML的需求,显示的告诉告诉Oracle要更新哪个表 和其他类型触发器不同的是,INSTEAD OF 触发器实际上并不是由某个事件触发的 语法:CREATE OR REPLACE TRIGGER trigger_name INSTEAD OF operation --delete,updat
SELECT INTO 技巧:0 & 1问题
当我们必须从一个表选择数据插入到临时变量,但所选的数据或者存在或者不存在 也就是返回或者0行或者1行 那么该如何有效的避免数据不存在的情况? 下面有几种技巧,希望可以帮到你 方法一:DECLARE l_sal emp.sal%TYPE; p_empno emp.empno%TYPE := 123; -- Invalid empno
PLS_INTEGER类型对性能的些许奉献
如果用PLS_INTEGER值运算,Oracle会使用原生机器算法 其他的所有数值型的数据类型都和NUMBER数据类型一样使用C语言算法库 结果就是PLS_INTEGER值的处理速度比NUMBER型的整数快很多 而且,PLS_INTEGER在移植硬件平台时不会遇到兼容性问题 对于密集型的整数运算,Think
显示游标的使用详解
显示游标就是在声明单元明确定义的SELECT子句,并同时指定一个名字 通过这个名字规范化地引用游标属性,同时在OPEN,FETCH,CLOSE语句中通过名字来引用显示游标 INSERT,UPDATE,DELETE或者MERGE都没有显示游标这一说 ㈠ 声明显示游标 语法: CURSOR cu
浅析IF和ELSIF的不平等
之前写过一篇博客,叫:Oracle PL/SQL 从if 到 then的“艺术鉴赏”,地址:点击打开链接 现在范围扩展至每个平行的IF条件,是否应该注意点啥 在条件是平行的时候,是否IF一定是可以无序的呢? 先看个小实验:hr@ORCL> ed Wrote file afiedt.buf 1 create or replace procedure p_test_if(p_num pls_integer) 2 as 3 v_num
DML触发器的缺憾
TOM说过他希望三样东西不曾存在:触发器,自治事务,WHEN OTHERS 级联删除、级联修改,在设计良好的系统中是不存在的 即使有,那也是小概率事件,必须专门写一段脚本来解决,而不是作为常规功能存在 不得不用触发器,要么是原系统模块化做得不够好,要么是不允许改动原有的
异常的定义、抛出和处理
任何错误都叫异常,不期而遇时,执行单元必须交割控制权,这是一个肉包子打狗--有去无回的过程 PL/SQL引擎对系统异常、用户异常或者应用异常皆是一视同仁 异常仅是异常吗?有些异常如NO_DATA_FOUND,我们更愿意待他是逻辑的一个分支 下面详细介绍异常的定义、抛出和处理 ㈠
PL/SQL每日一题:含有NULL的IF条件
哪些选项在执行之后会显示"Hello Earth"?(A) DECLARE l_total NUMBER; l_name VARCHAR2 (10) := \'PL/SQL\'; BEGIN IF l_name = \'PL/SQL\' OR l_total > 100 THEN DBMS_OUTPUT.put_line (\'Hello Earth\'); ELSE DBMS_OUTPUT.put_line (\'Hello Moon\'); END IF; END; / (B) DECLARE l_total NUMBER; l_name VARCHAR2 (10) := \'PL/SQL\'; BEGIN IF l_total > 100 THEN DBMS_OUTPUT.put_line (\'Hello Earth\'); ELSE
编写健壮的PL/SQL代码(一):同字段同类型、%TYPE、SUBTYPE
面对每天繁重的开发任务和交付工期的压力 我们不会花太多的时间(更多的时候是根本没时间去考虑或经验不够丰富)考虑自己的代码在未来会如何? 或者说在相关环境变化后还能否工作?面对需求变化被修改的量有多大? 说的直白一点,就我们写出的代码没有前瞻性,不够健壮,自适应能力太差 将
PL/SQL每日一题:CASE语句和CASE表达式的区别
题目: 世界上有很多不同品种的豚鼠,其中有一些具有可以识别的特征。比如:“埃塞俄比亚人(Abyssinians)”外皮上具有带褶皱的花环 “特塞尔绵羊(Texels)”有长长的卷毛。而“克雷斯特白豚鼠White Crested Guinea Pig”在头上一个白色的花纹(不出所料)
PL/SQL每日一题:TABLE()和集合类型定义
题目: 我执行了这些语句:CREATE OR REPLACE TYPE plch_numbers_nt IS TABLE OF NUMBER; / CREATE OR REPLACE TYPE plch_numbers_vat IS VARRAY (10) OF NUMBER; / CREATE OR REPLACE PACKAGE plch_pkg IS TYPE plch_numbers_nt IS TABLE OF NUMBER; END; / CREATE OR REPLACE TYPE plch_numbers_aat IS TABLE OF NUMBER INDEX BY PLS_INTEGER; / 然后我写了如下的不完整代
PL/SQL每日一题:输出负数
题目: 哪些选项输出一个负数?如果你确信以下都不对,那么请选EA DECLARE l_date2 DATE := date \'2012-12-20\'; l_date1 DATE := l_date2 - 1; BEGIN DBMS_OUTPUT.put_line (MONTHS_BETWEEN (l_date1, l_date2)); END; / B DECLARE l_date1 DATE := date \'2012-12-20\'; l_date2 DATE; BEGIN DBMS_OUTPUT.put_line (MONTHS_BETWEEN (l_date1, l_date2));
PL/SQL每日一题:异常处理--WHEN子句
题目: 捕获除数为零的错误("ORA-01476: divisor is equal to zero")并且在这种情况下显示 "Bad division" 所有的其他异常都必须原封不动地传播到调用块 换句话说,如果我加入下列异常处理部
理解游标(3)隐式游标的使用
当我们执行DML或Select into时,PL/SQL引擎会为我们声明一个隐式游标并管理这个游标 之所以谓之“隐式”是因为和游标相关的工作数据库已经替我们自动做好了 我们使用隐式游标,实际就是期待返回一行,这里有一个原则: 对于单行记录查询,我们应该总是将它封装到一个位于包里的函