分享
 
 
 

Expert One-on-One Oracle阅读笔记(3)

王朝oracle·作者佚名  2006-01-31
窄屏简体版  字體: |||超大  

绑定地址

bln

绑定缓冲区大小

avl

真实值长度

flag

内部标记

value

绑定值的字符串表示(如果可能,会是一个十六进制dump)

其中dty:SELECT text

FROM ALL_VIEWS WHERE view_name = ‘USER_VIEWS’ 可看到一个将dty数值转换为字符串表示的函数。

此后我们可以看到WAIT段,即真正的等待事件。

对于ENQUEUE事件,实际就是锁。可用以下函数(传入参数为p1)判断类型:

CREATE OR REPLACE FUNCTION

enqueue_decode(l_p1

in number) return varchar2

AS

l_str

varchar2(25);

BEGIN

SELECT

CHR(BITAND(l_p1, -16777216) / 16777215) ||

CHR(BITAND(l_p1, 16711680) / 65535) || ‘

‘ ||

DECODE(BITAND(l_p1, 65535),

0, ‘No lock’,

1, ‘No lock’,

2, ‘Row-Share’,

3, ‘Row-Exclusive’,

4, ‘Share’,

5, ‘Share Row-Excl’,

6, ‘Exclusive’ )

INTO

l_str

FROM

DUAL;

RETURN

l_str;

END;

XCTEND(事务边界)段记录了提交等:

rlbk

回滚标记:0

提交

1 回滚

rd_only

只读标记:0

变化提交或回滚

1 事务只读

STAT段记录了运行时SQL真正的执行计划:

cursor #

游标号

id

执行计划行号

cnt

查询计划中流经此步骤的行数

pid

此步骤的父ID

pos

执行计划中的位置

obj

访问的对象的对象ID

op

操作的文本描述

PARSE

ERROR段

len

SQL语句长度

dep

SQL语句递归深度

uid

分析的方案

oct

Oracle命令类型

lid

权限方案ID

tim

定时器

err

ORA错误代码

ERROR段

cursor #

游标数

err

ORA错误代码

tim

定时器

10.5

DBMS_PROFILER

10.6

StatsPack

10.7 V$表

V$EVENT_NAME

说明事件名和p1、p2、p3三个参数。

V$FILESTAT和V$TEMPSTAT

说明系统I/O概况。

V$LOCK

说明系统锁的情况。但注意Oracle并不在外部保存行锁,此视图可以找到TM(DML

Enqueue)锁,即说明产生了行锁。

V$MYSTAT

说明当前会话的统计信息。需要V_$STATNAME(不用V$STATNAME,只是V_$STATNAME的一个同义词)和V_$MYSTAT上的SELECT权限。

CREATE VIEW MY_STATS

AS

SELECT a.name,

b.value

FROM V$STATNAME a, V$MYSTAT

b

WHERE a.statistic# =

b.statistic#;

V$OPEN_CURSOR

记录所有会话打开的游标。由于Oracle也会缓存已关闭的游标,因此此视图中也会包含已关闭的游标信息。

V$PARAMETER

说明了所有的init.ora参数。

V$SESSION

记录数据库的每个会话。需要对V_$SESSION的SELECT权限。

V$SESSION_EVENT

说明会话的事件情况。

V$SESSION_LONGOPS

记录CBO认为执行时间超过6秒的命令及进展。

V$SESSION_WAIT

记录所有正在等待某事件的会话及已等待时间。

V$SESSTAT

类似V$MYSTAT,但显示所有会话。

V$SESS_IO

说明会话的I/O信息

V$SQL和V$SQLAREA

记录SQL信息。建议使用V$SQL,V$SQLAREA是从V$SQL合并而来的视图,代价较高,对已经繁忙的系统是一个负担。

V$STATNAME

说明了统计号到统计名的映射。

V$SYSSTAT

记录实例层面的统计信息。当数据库关闭时才清空,也是StatsPack很多数据的来源。

V$SYSTEM_EVENT

记录实例层面的等待事件信息。也是StatsPack很多数据的来源。

第 11

章 优化器计划稳定性

11.1 概览

CREATE OR REPLACE ONLINE

MyOutLine

FOR CATEGORY

mycategory

ON

SELECT

……;

需要CREATE

OUTLINE权限

使用时指定会话的CATEGORY即可:

ALTER SESSION SET USE_STORED_OUTLINES =

mycategory;

11.2 OPS的使用

对已封装的应用中SQL进行的优化方法

ALTER SESSION SET CREATE_STORED_OUTLINES =

test;

执行应用,如一个存储过程等

ALTER SESSION SET CREATE_STORED_OUTLINES =

FALSE;

SET LONG 5000

SELECT name, sql_text FROM user_outlines WHERE

category = ‘test’;

此时可以看到所运行的SQL语句。也可以通过一个ON

LOGON触发器来实现,即一登陆就ALTER

SESSION…

优化时修改OPTIMIZER_GOAL后:

ALTER SESSION SET OPTIMIZER_GOAL =

FIRST_ROWS;

ALTER OUTLINE name

REBUILD;

ALTER SESSION SET OPTIMIZER_GOAL =

CHOOSE;

此时就固定为OPTIMIZER_GOAL

= FIRST_ROWS时的执行计划了。

一个开发工具

由于开发环境与实际部署环境可能不一致,为了保证执行计划与开发环境一致,可以建立一个ON

LOGON触发器来将执行计划归入一个category中,然后exp/imp到新环境中。

用来观察是否使用了索引

SELECT name, hint FROM

user_outline_hints

WHERE hink LIKE

‘INDEX%’;

用来观察应用使用了什么SQL语句

11.3 OPS如何工作

OUTLINES与OUTLINE_HITS

均分别有DBA_、USER_、ALL_三张视图,其中DBA_多一个owner字段,说明创建者,另两张与用户有关系。

DBA_OUTLINES:

NAME

OUTLINE名,若创建时未指定,则使用系统命名

OWNER

创建时的方案名

CATEGORY

创建的列别,若未指定则为DEFAULT

USED

是否使用过

TIMESTAMP

创建的时间

VERSION

创建时的数据库版本

SQL_TEXT

SQL查询语句

DBA_OUTLINE_HINTS:

NAME

OUTLINE名,若创建时未指定,则使用系统命名

OWNER

创建时的方案名

NODE

提示应用的层次,从最外层查询(1)开始累加计数

STAGE

提示应用的阶段,即提示在编译的哪个阶段写入

JOIN_POS

提示应用的表名,对非访问方式提示为0

HINT

提示

11.4 创建存储概要

相关的权限

CREATE ANY

OUTLINE – 创建概要,否则报ORA-18005错误

ALTER ANY

OUTLINE – 修改或重新计算概要

DROP ANY

OUTLINE – 删除概要

EXECUTE ON

OUTLN_PKG – 执行OUTLINE包

注意这里权限都是全局的,概要不存在真正的所有者。

使用DDL

CREATE <OR REPLACE> OUTLINE

OUTLINE_NAME

<FOR CATEGORY

CATEGORY_NAME>

ON STATEMENT

使用ALTER SESSION

ALTER SESSION SET CREATE_STORED_OUTLINES =

TRUE;

ALTER SESSION SET CREATE_STORED_OUTLINES =

FALSE;

ALTER SESSION SET CREATE_STORED_OUTLINES =

mycategory;

当设为TRUE时,所创建的概要归类入DEFAULT。

11.5 OUTLN用户

所有8i数据库中均缺省创建,缺省密码为OUTLN,并可在安装后立即更改。方案含有两个表和一些索引,存放于SYSTEM表空间中,若需要大量使用概要,可用如下方法转移表空间(其中一张表含有LONG类型字段,无法ALTER TABLE

MOVE)。

EXP USERID=OUTLN/OUTLN

OWNER=OUTLN

ALTER USER OUTLN DEFAULT TABLESPACE

tools;

REVOKE UNLIMITED TABLESPACE FROM

OUTLN;

ALTER USER OUTLN QUOTA 0K ON

SYSTEM;

ALTER USER OUTLN QUOTA UNLIMITED ON

tools;

DROP TABLE ol$;

DROP TABLE

ol$hints;

IMP USERID=OUTLN/OUTLN

FULL=YES

若系统已经使用了概要,则操作应尽量在单用户模式下执行,数据库无其它活动终端用户。

11.6 在数据库间转移概要

EXP USERID=OUTLN/OUTLN QUERY=”where category=’test’”

tables=(ol$, ol$hints)

IMP USERID=OUTLN/OUTLN FULL=Y

IGNORE=YES

这里也可以使用参数文件来定义导出的查询条件。

11.7 获得正确的概要

有时仅修改某些参数是无法获得所需要的执行计划的,还要添加提示。但概要的使用是基于相同的SQL文本,为了不修改应用但使用添加了提示的执行计划,可以采用如下方法:

例如需要SELECT FROM

(SELECT /*+ use_hash(emp) */ FROM emp)

emp,

(SELECT /*+ use_hash(dept) */ FROM dept)

dept

WHERE

emp.deptno=dept.deptno;

则可以在另一个方案中删除emp、dept表,将内层查询语句建立成名为emp和dept的视图,然后对SELECT *

FROM emp,dept WHERE emp.deptno=dept.deptno; 建立概要。则此后可以指定应用使用此概要(SQL文本一致)。

这也是利用了OPS是全局的,并不关心所引用对象,而是纯粹根据SQL文本进行转换。

11.8 管理概要

通过DDL

ALTER OUTLINE outline_name RENAME TO

new_name;

ALTER OUTLINE outline_name CHANGE CATEGORY TO

new_category_name;

ALTER OUTLINE outline_name

REBUILD;

DROP OUTLINE

outline_name;

OUTLN_PKG包

作用:提供批量管理的功能;提供EXP/IMP的API

由DBMSOL.SQL和PRVTOL.PLB脚本(%ORACLE_HOME%/RDBMS/ADMIN)创建,而这两个脚本由CATPROC.SQL调用并缺省安装到数据库。

DROP_UNUSED

– 删除所有类别中所有未使用的概要。

EXEC

OUTLN_PKG.DROP_UNUSED;

DROP_BY_CAT

– 删除指定类别中的所有概要。

EXEC

OUTLN_PKG.DROP_BY_CAT(category_name);

UPDATE_BY_CAT

– 重命名一个类别或将其合并入另一个类别。

EXEC

OUTLN_PKG.UPDATE_BY_CAT(old_category_name, new_category_name); 若新名已被用,则合并,且若新旧类别存在相同SQL文本的概要,保留新类别中的,而此重复的概要仍保留于原类别中。

11.9 最后说明

创建概要需要CREATE ANY

OUTLINE权限,若无权限,利用ALTER

SESSION方式来创建概要时不会提示错误,但不会创建概要。

删除用户时即便指定CASCADE选项,也不会删除其创建的概要。

如果CURSOR_SHARING设为force,则用DDL和ALTER

SESSION两种方法获得的SQL文本可能是不同的,前者就是输入的SQL,而后者是系统内部已经转换过绑定变量的SQL。

概要的使用依靠文本完全匹配,即便是大小写不同也会造成SQL文本不匹配。

OR扩展问题:由于WHERE条件中有OR的SQL会被改写为UNION

ALL模式,概要记录的提示可能无法正常使用,而只是作用到第一个条件上。因此要注意USER_OUTLINE_HINTS表中HINT LIKE

‘USE_CONCAT%’的概要和提示,应当删除或移走。

使用概要对性能影响很小。创建概要时接近首次分析该条语句的时间,此后第一次分析慢于正常分析时间,而随后概要已经进入缓存,将不会观察到性能影响。

11.10 可能遇到的错误

ORA-18001 – 使用ALTER OUTLINE语法错误

ORA-18002 – 所引用的概要不存在(从未创建过或者被删除)

ORA-18003 – 概要的数字签名已存在,数字签名用于快速查找到合适的概要,此错误极少发生

ORA-18004 – 概要已存在,一般是命名冲突

ORA-18005 – 需要CREATE ANY OUTLINE权限

ORA-18006 – 需要DROP ANY OUTLINE权限

ORA-18007 – 需要ALTER ANY OUTLINE权限

第 12

章 分析函数

12.1 分析函数如何工作

语法

FUNCTION_NAME(<参数>,…)

OVER

(<PARTITION BY

表达式,…> <ORDER BY 表达式 <ASC | DESC> <NULLS FIRST | NULLS LAST>>

<WINDOWING子句>)

PARTITION子句

ORDER BY子句

WINDOWING子句

缺省时相当于RANGE UNBOUNDED PRECEDING

1. 值域窗(RANGE WINDOW)

RANGE N PRECEDING

仅对数值或日期类型有效,选定窗为排序后当前行之前,某列(即排序列)值大于/小于(当前行该列值

–/+ N)的所有行,因此与ORDER BY子句有关系。

2. 行窗(ROW WINDOW)

ROWS N PRECEDING

选定窗为当前行及之前N行。

还可以加上BETWEEN AND 形式,例如RANGE BETWEEN m PRECEDING AND n

FOLLOWING

函数

AVG(<distinct | all> expr)

一组或选定窗中表达式的平均值

CORR(expr,

expr)

即COVAR_POP(exp1,exp2) / (STDDEV_POP(expr1) *

STDDEV_POP(expr2)),两个表达式的互相关,-1(反相关) ~ 1(正相关),0表示不相关

COUNT(<distinct> <*> <expr>)

计数

COVAR_POP(expr, expr)

总体协方差

COVAR_SAMP(expr, expr)

样本协方差

CUME_DIST

累积分布,即行在组中的相对位置,返回0 ~ 1

DENSE_RANK

行的相对排序(与ORDER BY搭配),相同的值具有一样的序数(NULL计为相同),并不留空序数

FIRST_VALUE

一个组的第一个值

LAG(expr,

<offset>, <default>)

访问之前的行,OFFSET是缺省为1 的正数,表示相对行数,DEFAULT是当超出选定窗范围时的返回值(如第一行不存在之前行)

LAST_VALUE

一个组的最后一个值

LEAD(expr,

<offset>, <default>)

访问之后的行,OFFSET是缺省为1 的正数,表示相对行数,DEFAULT是当超出选定窗范围时的返回值(如最后行不存在之前行)

MAXexpr)

最大值

MIN(expr)

最小值

NTILE(expr)

按表达式的值和行在组中的位置编号,如表达式为4,则组分4份,分别为1 ~ 4的值,而不能等分则多出的部分在值最小的那组

PERCENT_RANK

类似CUME_DIST,1/(行的序数 - 1)

RANK

相对序数,允许并列,并空出随后序号

RATIO_TO_REPORT(expr)

表达式值 / SUM(表达式值)

REGR_

xxxx(expr, expr)

线性回归函数

ROW_NUMBER

排序的组中行的偏移

STDDEV(expr)

标准差

STDDEV_POP(expr)

总体标准差

STDDEV_SAMP(expr)

样本标准差

SUM(expr)

合计

VAR_POP(expr)

总体方差

VAR_SAMP(expr)

样本方差

VARIANCE(expr)

方差

12.2 例子

竖表转横表

一般形式为将一个列为C!, C2, … CN的表,以C1, C2, … CX为基准,将CX+1, … CN的不同值改为列。一般化的语法:

SELECT C1, C2, … CX,

MAX(DECODE(rn, 1, CX+1, NULL)) CX+1_1, … MAX(DECODE(rn, 1, CN, NULL))

CN_1

MAX(DECODE(rn, 2, CX+1, NULL)) CX+1_2, … MAX(DECODE(rn, 2, CN, NULL))

CN_2

MAX(DECODE(rn,N,CX+1, NULL)) CX+1_N, … MAX(DECODE(rn,N, CN, NULL))

CN_N

FROM

(SELECT C1, C2, …

CN,

ROW_NUMBER() OVER (PARTITION

BY C1, C2, … CX ORDER BY <something>) rn

FROM T

WHERE …)

GROUP BY C1, C2, … CX;

通用包:

CREATE OR REPLACE PACKAGE

pkg_pivot

AS

TYPE refcursor IS REF CURSOR;

TYPE ARRAY IS TABLE OF VARCHAR2(30);

PROCEDURE pivot(p_max_cols IN NUMBER DEFAULT

NULL,

p_max_cols_query IN VARCHAR2

DEFAULT NULL,

p_query IN

VARCHAR2,

p_anchor IN

ARRAY,

p_pivot IN

ARRAY,

p_cursor IN OUT

refcursor);

END;

CREATE OR REPLACE PACKAGE BODY

pkg_pivot

AS

PROCEDURE pivot(p_max_cols IN NUMBER DEFAULT

NULL,

p_max_cols_query IN VARCHAR2

DEFAULT NULL,

p_query IN

VARCHAR2,

p_anchor IN

ARRAY,

p_pivot IN

ARRAY,

p_cursor IN OUT

refcursor)

AS

l_max_cols NUMBER;

l_query LONG;

l_cnames ARRAY;

BEGIN

IF (p_max_cols IS NOT NULL)

THEN

EXECUTE IMMEDIATE p_max_cols_query INTO

l_max_cols;

ELSE

RAISE_APPLICATION_ERROR(-20001, 'Cannot

figure out max cols');

END IF;

l_query := 'select ';

FOR i IN 1 .. p_anchor.count

LOOP

l_query := l_query || p_anchor(i) ||

',';

END LOOP;

FOR i IN 1 .. l_max_cols

LOOP

FOR j IN 1 ..

p_pivot.count

LOOP

l_query := l_query ||

'max(decode(rn,'||i||','||p_pivot(j)||',null)) '||p_pivot(j) || '_' || i ||

',';

END LOOP;

END LOOP;

l_query := RTRIM(l_query,',') || ' from (' || p_query || ') group by

';

FOR i IN 1 .. p_anchor.count

LOOP

l_query := l_query || p_anchor(i) ||

',';

END LOOP;

l_query := RTRIM(l_query,',');

EXECUTE IMMEDIATE 'alter session set

cursor_sharing=force';

OPEN p_cursor FOR l_query;

EXECUTE IMMEDIATE 'alter session set

cursor_sharing=exact';

END;

END;

其中:

p_max_cols_query为SELECT MAX(COUNT(*)) FROM TABLE_NAME GROUP BY C1, C2, …

CX;

p_query为SELECT C1, C2, … CN ROW_NUMBER() OVER (PARTITION BY C1, C2, … CX

ORDER BY <something>) rn FROM TABLE_NAME;

p_anchor为pkg_pivot.array(C1, C2, … CX)

p_pivot为pkg_pivot.array(CX+1, CX+2, … CN)

p_cursor为返回的游标。

12.3 最后说明

PL/SQL与分析函数

PL/SQL不支持分析函数的语法,可以通过以下两种方法解决:

1.使用动态游标;

2.将含分析函数的语句创建为视图。

WHERE子句中的分析函数

由于查询仅在最后的ORDER BY子句前执行分析函数,因此WHERE条件中无法使用分析函数,只能利用嵌套循环实现。

第 13

章 物化视图

8.1.5企业版/个人版开始支持

需要权限:GRANT CREATE MATERIALIZED VIEW,还必须直接赋予GRANT QUERY REWRITE。为实现查询重写,必须使用CBO。

13.1 物化视图如何工作

设置

COMPATIBLE参数必须高于8.1.0

QUERY_REWRITE_ENABLED = TRUE

QUERY_REWRITE_INTEGRETY =

ENFORCED - 查询仅用Oracle强制与保证的约束、规则重写;

TRUSTED – 查询除用Oracle强制与保证的约束、规则,也可用用户设定的数据间的任何关系来重写;

STALE_TOLERATED – 即便Oracle知道物化视图中数据过期(与事实表等不同步),也重写查询。

创建物化视图的用户必须具有直接赋予的GRANT QUERY REWRITE权限,不能通过角色继承。

内部机制

全文匹配

部分匹配:从FROM子句开始,优化器比较之后的文本,然后比较SELECT列表

一般重写方法:

数据充分

关联兼容

分组兼容

聚集兼容

13.2 确保使用物化视图

约束

考虑到现实环境的数据量,可以将主键、外键、非空等约束置为NOVALIDATE,并调整QUERY_REWRITE_INTEGRITY为TRUSTED,这样可以达到“欺骗”数据库的目的,但必须注意如果无法保证此类约束的真实有效,查询改写后可能造成结果不精确。

维度

实际就是指明已存在的表中各列的归并关系,从而关联事实表后形成的物化视图可用于向“上”归并(相当于用表中代表更高归并关系的列关联事实表)。标准语法:

CREATE DIMENSION

time_hierarchy_dim

LEVEL day IS

time_hierarchy.day

LEVEL mmyyyy IS

time_hierarchy.mmyyyy

LEVEL yyyy IS

time_hierarchy.yyyy

HIERARCHY time_rollup

(day CHILD OF mmyyyy CHILD OF

yyyy)

ATTRIBUTE mmyyyy

DETERMINES mon_yyyy;

13.3

DBMS_OLAP

估计(物化视图)大小

DBMS_OLAP.ESTIMATE_SUMMARY_SIZE(视图名, 视图定义, 估计行数, 估计字节数);

其中后两个参数为NUMBER型输出参数。

维度有效性检查

DBMS_OLAP.VALIDATE_DIMENSION(视图名, 用户名, FALSE, FALSE);

SELECT * FROM 维度表名

WHERE ROWIN IN (SEELCT bad_rowid FROM

MVIEW$_EXCEPTION);

所选出行即为不符合维度定义的行。

推荐物化视图

首先必须添加合适的外键,包通过外键来判定表之间的关系而不是维度。

DBMS_OLAP.RECOMMEND_MV(事实表名, 1000000000, ‘’);

第二个参数表示物化视图可用的空间大小,可传入一个较大的数。第三个参数传入需要保留的特定物化视图,传入空即为不考虑其他物化视图。

执行C:\oracle\RDBMS\demo\sadvdemo后执行:

DEMO_SUMADV.PRETTYPRINT_RECOMMENDATIONS

13.4 最后说明

物化视图不为OLTP系统设计

在事实表等更新时会导致物化视图行锁,从而影响系统并发性。

第 14

章 分区

14.1 分区的使用

增加可用性

减轻维护负担

提高DML与查询的性能

14.2 分区如何工作

表分区策略

索引分区

本地索引

分为本地前缀索引(Local Prefixed Index)、本地非前缀索引(Local Non-prefixed Index)

1. 索引的选择

在单表查询中,本地非前缀索引可能增加可用性,也更加实用。例如表T(a, b)按a区间分区,若在b上建立本地索引,则当某个分区离线,仅查询b的某个值时,该索引可用,而索引(a, b)不可用;删除索引(a, b),查询(a, b)的某对值,b上的索引仍可用。此时若建立索引(b, a),则可应对各类查询。

在多表关联(如上例中按照(a, b)值关联)时,系统将发现代价较高而不会用到本地非前缀索引(如上例中(b, a))。

因此建立本地索引时应当考虑通常的使用环境。

2. 无法基于本地非前缀索引建立唯一键或主键。

全局索引

仅有一种,即全局前缀索引

1. 数据仓库环境

在(与建立好相应索引的表)交换分区与索引或分割分区后,全局索引将失效而必须重建,因此全局索引并不适合数据仓库。

例如:

ALTER TABLE

partitioned

EXCHANGE PARTITION

fy_1999

WITH TABLE

fy_1999

INCLUDING INDEXES

WITHOUT

VALIDATION;

ALTER TABLE

partitioned

SPLIT PARTITION

the_rest

AT

(TO_DATE(‘200101’,

’yyyymm’))

INTO (PARTITION fy_2000, PARTITION

the_rest);

2. OLTP环境

一定程度上增加了可用性。当某些分区离线,不含有用于分区的列且合乎查询条件的数据存在于在线分区的索引仍然是可用的,对于不需要查询全表而是通过索引即可得到结果的查询也是有效的(例如COUNT非用于分区的列等)。

第 15

章 自治事务

DECLARE

PRAGMA

AUTONOMOUS_TRANSACTION;

15.1 为何使用自治事务

无法回滚的审计

一般情况下利用触发器禁止某些对表的更新等操作时,若记录日志,则触发器最后抛出异常时会造成日志回滚。利用自治事务可防止此点。

避免变异表

即在触发器中操作触发此触发器的表

在触发器中使用DDL

写数据库

对数据库有写操作(INSERT、UPDATE、DELETE、CREATE、ALTER、COMMIT)的存储过程或函数是无法简单的用SQL来调用的,此时可以将其设为自治事务,从而避免ORA-14552(无法在一个查询或DML中执行DDL、COMMIT、ROLLBACK)、ORA-14551(无法在一个查询中执行DML操作)等错误。需要注意的是函数必须有返回值,但仅有IN参数(不能有OUT或IN/OUT参数)。

开发更模块化的代码

在大型开发中,自治事务可以将代码更加模块化,失败或成功时不会影响调用者的其它操作,代价是调用者失去了对此模块的控制,并且模块内部无法引用调用者未提交的数据。

15.2 如何工作

事务控制

DECLARE整个块都是属于父事务的,自治事务从离PRAGMA后的第一个BEGIN开始,只要此BEGIN块仍在作用域,则都属于自治事务。例如在DECLARE模块中声明一个写数据库的函数,则此函数虽然在自治事务所在存储过程执行,但其属于父事务;而自治事务中调用的任何函数和存储过程、激发的任何触发器等均为此自治事务的一部分。

自治事务可以嵌套,嵌套深度等只受INIT.ORA参数TRANSACTIONS(同时并发的事务数,缺省为SESSIONS的1.1倍)制约。

作用域

1. 包中的变量

自治事务可看到并修改父事务的变量,父事务也会察觉到这一改变,且不存在回滚问题。

2. 会话设置/参数

自治事务与父事务共享同一个会话环境,通过ALTER SESSION作的修改对整个会话均有效。但SET TRANSACTION是事务级的,仅对提起修改的事务有效。

3. 数据库修改

父事务已提交的修改对自治事务可见,未提交的对自治事务不可见,自治事务的修改对父事务是否可见取决于隔离级别(Isolation Level)。

对于游标,取决于其打开的位置,若其在父事务中打开,则之前父事务未提交的修改对其是有效的,在自治事务中这些修改也可见;而在自治事务中打开,则父事务未提交的修改不可见。

若使用缺省的READ COMMITTED隔离级别,则自治事务的修改对父事务可见;若改用SERIALIZABLE,则不可见。

4. 锁

父事务与自治事务是完全不同的事务,因此无法共享锁等。

结束一个自治事务

必须提交一个COMMIT、ROLLBACK或执行DDL。

保存点

无法在自治事务中回滚到父事务中的一个保存点,只能在内部使用保存点。

15.3 最后说明

不支持分布式事务

截至8.1.7在自治事务中不支持分布式事务

仅可用PL/SQL

全部事务回滚

若自治事务出错,则全部回滚,即便父事务有异常处理模块。

事务级临时表

每个会话仅一个事务可访问事务级临时表(多个会话中的事务可并发操作)。

变异表

15.4 可能遇到的错误

ORA-06519 – 检查到活动自治事务,回滚——退出自治事务时没有提交、回滚或DDL操作

ORA-14450 – 试图访问正在使用的事务级临时表

ORA-00060 – 等待资源时检查到死锁

第 16 章 动态SQL

16.1 为何使用动态SQL

实现动态SQL有两种方式:DBMS_SQL和本地动态SQL(EXECUTE IMMEIDATE)

主要从以下方面考虑使用哪种方式:

1. 是否知道涉及的列数和类型

DBMS_SQL包括了一个可以“描述”结果集的存储过程(DBMS_SQL.DESCRIBE_COLUMNS),而本地动态SQL没有。

2. 是否知道可能涉及的绑定变量数和类型

DBMS_SQL允许过程化的绑定语句的输入,而本地动态SQL需要在编译时确定。

3. 是否使用“数组化”操作(Array

Processing)

DBMS_SQL允许,而本地动态SQL基本不可以,但可以用其他方式实现(对查询可用FETCH BULK

COLLECT INTO,对INSERT等,可用一个BEGIN …

END块中加循环实现)。

4. 是否在同一个会话中多次执行同一语句

DBMS_SQL可以分析一次执行多次,而本地动态SQL会在每次执行时进行软分析。

5. 是否需要用REF

CURSOR返回结果集

仅本地动态SQL可用REF

CURSOR返回结果集。

16.2 如何使用动态SQL

DBMS_SQL

1. 调用OPEN_CURSOR获得一个游标句柄;

2. 调用PARSE分析语句。一个游标句柄可以用于多条不同的已分析语句,但一个时间点仅一条有效;

3. 调用BIND_VARIABLE或BIND_ARRAY来提供语句的任何输入;

4. 若是一个查询(SELECT语句),调用DIFINE_COLUMN或DEFINE_ARRAY来告知Oracle如何返回结果;

5. 调用EXECUTE执行语句;

6. 若是一个查询,调用FETCH_ROWS来读取数据。可以使用COLUMN_VALUE从SELECT列表根据位置获得这些值;

7. 否则,若是一个PL/SQL块或带有RETURN子句的DML语句,可以调用VARIABLE_VALUE从块中根据变量名获得OUT值;

8. 调用CLOSE_CURSOR。

注意这里对任何异常都应该处理,以关闭游标,防止泄露资源。

本地动态SQL

EXECUTE

IMMEDIATE ‘语句’

[INTO

{变量1,

变量2, …

变量N |

记录体}]

[USING [IN

| OUT | IN OUT] 绑定变量1, …

绑定变量N]

[{RETURNING

| RETURN} INTO 输出1 [, …,

输出N]…];

注意本地动态SQL仅支持弱类型REF

CURSOR,即对于REF CURSOR,不支持BULK

COLLECT。

16.3 最后说明

动态SQL的负面:破坏了依赖链、代码更脆弱、很难调优。

第 17

interMedia

第 18 章 基于C的外部过程

第一頁    上一頁    第3頁/共3頁    下一頁    最後頁
第01頁 第02頁 第03頁 
 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有