a我考网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 562|回复: 4

[考试辅导] Oracle中提取和存储数据库对象的DDL

[复制链接]
发表于 2012-8-4 14:06:19 | 显示全部楼层 |阅读模式
从对象(例如数据库表、索引、约束、触发器等)中提取DDL命令的普通方法涉及到的操作包括从这些对象中提取元数据(metadata),并把这些数据存储在内存中。尽管目前有很多脚本可以实现这样的功能,但是它们通常都是不完整的或者过时的。幸运的是,Oracle 9.2提供了一个实现这样的功能的API:DBMS_METADATA程序包。
  Z8 j. K/ q% J% Y( |% ~1 G5 I8 H# `) I9 b
  在很多情况下,数据库中数据的维护操作要求我们提取多种对象(例如数据库表、索引、约束、触发器等)的DDL(Data Definition Language,数据定义语言)。: C+ [8 s% ^" C4 o# o
( [' `7 w/ U. N, E7 i  [
  最近我承担了一个任务,我需要编写一组数据库程序包来执行高性能的大量的数据删除(DELETE)操作。这样的操作要求我拥有提取和存储数据库对象DDL的相关技术。) X" d, b+ `7 s9 l2 u1 }4 w: |0 Q

7 C/ c2 |1 {1 ]3 U+ o0 {+ S  r- D  提取和存储数据库对象的DDL的方法如下:
; v4 F7 k2 f$ f; F' K* I  j' b! V% k9 t( U. E4 Y
  · 建立与源表结构相同的数据表,但是它不带主键、备用键和外部键约束。
2 q* L" ~4 }6 l$ u3 ^3 T
% I4 ~( V2 G! w  · 例如,使用MyTable_X,其中MyTable是要被删除的目标数据表。% K* g  u  d4 ]% J
" `- ]1 T: R3 j9 {
  · 把需要保存的数据插入新建立的数据表(MyTable_X)中。7 D9 c& n" j5 p
" r6 T& g; G% u  d0 K) G
  · 使用NOLOGGING PARALLEL选项在新数据表上建立索引。
0 ~2 M, B3 F2 f9 _6 a  G# R
" o! i% _4 K/ M  · 在新数据表上建立约束。
4 g* \1 ~! ]' G8 [2 c. I; p! o3 i# r) e0 _6 R% p% Z8 j
  · MyTable和MyTable_X数据表进行交换。把主表改名为MyTable_T,把MyTable_X改名为MyTable。  Z! P8 i  y. n! J. t- ?" a
4 u( M2 G$ J& w
  · 验证结果并删除MyTable_T表。! M) t, `& f3 {7 Y% Y

" f& A2 D* y( I  很明显,为了编写实现上面目标的代码,你必须提取数据库对象的元数据(定义和被选中的属性),并把它存储在内存中,这样在执行上面的操作的时候才能够使用它。6 S! Y5 [( g( N  `

+ v6 X5 D$ a2 c' P  在网上存在大量的脚本,它们可以从多种Oracle数据字典(user_tables、user_indexes、user_ind_columns、user_constraints、user_cons_columns等)中提取数据库对象的元数据,接着为特定的对象构造DDL命令。这些脚本的一个问题是,它们通常是SQL*Plus脚本,它会生成客户端文本文件,而这个文件不能被服务器端代码访问。它们的主要问题有:
7 R7 I- K5 |0 r: y- q
, D  r- Z5 N+ ?$ e  · 不完整:不能提取所有的选项,并组合进DDL语句中。
6 c' C5 f& ]# I: {2 @* q" o8 m2 K0 v  e
  · 过时了:这些脚本通常不支持Oracle最新的数据库特性--分区(partitioning)、基于函数的索引、自动段空间管理(ASSM)等。这些脚本可能崩溃或生成错误的DDL语句。
+ G7 K1 ?3 J8 }( w4 C
3 r9 @2 |. {( l$ O: A% j/ N: C  问题总结:尽管有大量的从Oracle数据字典中提取数据库对象元数据的脚本,但是它们中的大多数要么不完整,要么过期了。
( _0 l4 X# O& O8 w' l, j& B" h  c" t
  解决方案:使用DBMS_METADATA程序包,学习如何用最佳的、没有错误的和易于维护的方式执行上面的事务。8 o" {$ i% l$ S8 k/ D6 R
3 C0 Z! {: X& C- J7 p8 N2 V+ ^: g+ _
  使用Oracle的本地API:DBMS_METADATA程序包
4 ]+ C$ v* Y. E7 ^' j( R  K. r7 r# k+ q% n
  Oracle数据库采用补充PL/SQL程序包的形式提供了丰富的预先包装好的API。Oracle 9.2版本中引入的DBMS_METADATA程序包可能正好适合你的需求。它包含了用于检索数据库对象定义的API。! a6 a7 A7 t1 h' x% t- o% X- c
% `0 ~" @7 P4 f( l  |5 L5 a
  我们将使用的API主要是DBMS_METADATA.GET_DDL函数。这个函数返回的对象定义SQL字符串是CLOB。它拥有下面一些输入参数:
/ D! H+ m! I7 q6 G: v, \. T. @" h; a6 D7 q8 [. f
  · object_type VARCHAR2
$ w4 E& c; w% v- B  I. t8 V+ [
' z3 S; t/ t9 k  · name VARCHAR2 1 l* K: i: t7 x9 ]! f  k" z0 p3 F1 K

) {; e& Q8 {  t  · schema VARCHAR2 DEFAULT NULL
7 E3 Y( c, Q3 z7 t8 Z
% _7 Z/ ^! {: X, _' G' e6 U  · version VARCHAR2 DEFAULT ’COMPATIBLE’
( p5 t6 D! ^. p  [. o1 I1 I3 d9 |: F# m9 I* X; L+ u
  · model VARCHAR2 DEFAULT ’Oracle’,
& x, c) M  M: h0 I% M7 m! F2 }
  · transform VARCHAR2 DEFAULT ’DDL’ . f. C& R2 i. e  y& r( E

& }* ]( w( \: @6 Q, Q$ |  下面建立了一个用于测试的EmpTest数据表,它带有索引和约束:
# l) q: [% g! P8 U4 w2 E8 H: f3 R9 a7 k
create table EmpTest
* E, V/ `5 j& P+ Z$ u( {, H, p6 V(
0 I6 L' |4 t7 b1 c. [. K9 M" F+ C+ lempNo integer not null,
# T8 X4 [# Q6 a$ IlastName varchar2(30) not null,
' @9 w; g9 N* F2 F9 d! E0 G5 Z5 m3 J* JfirstName varchar2(20) not null,% ?0 G8 l! x, t" O8 T, a* _4 b
job varchar2(9) ’
& y/ i5 n3 f" J6 c  Q( OhireDate date ’+ J2 r1 j0 r' W+ ~, A
isActive number(1)
! Y* `7 J( V" f9 Zconstraint EmpTest_CK1
! O- K( l* E/ Vcheck (isActive in (0,1)) ,
1 J; N  O8 A: M+ h2 Zsalary number(9,2) ,# P/ M( B6 X3 p% Y
commision number(9,2) ,/ {+ V1 O( w: b9 v
deptNo number(2) ,: C( [* V* e, n) N* V; e7 i9 w
constraint EmpTest_PK8 z. B4 R0 ?3 c$ ]# c
primary key (empNo),7 O% y1 D* G/ l1 F+ I
constraint EmpTest_AK19 i! o$ h; X% M8 u1 V! u3 D; @2 j9 g
unique (lastName, firstName)
( a* c: j: l) r2 [# ^9 G);
# O1 O( E3 T) Y& n
* N/ n6 U; J% K# t$ Icreate index EmpTest_HireDate_Salary) h& F0 d7 V; z$ _2 E. i
on EmpTest
, k- ~) L* m* ?) B' j(9 I5 G! Z! ~0 |
salary,
6 u+ W& A& k6 z3 `: z" M; d1 k4 QhireDate
1 t  f- [/ `4 m3 d);; i4 z5 n/ v! o' f. K  y2 C: V
  运行上面的脚本之后,就建立了一个带有三个索引(两个唯一的和一个不唯一的索引)的EmpTest表:% B; H: M+ L4 C4 J2 Q

+ N8 h9 W7 \& y, R9 Z. Dselect index_name, index_type, uniqueness- F" ]7 a; X% I, X) c6 p2 \, z
from user_indexes7 H4 m5 E: F0 [. ]/ c  L
where table_name = ’EMPTEST’;
7 S+ ~, h  N9 W7 f4 {. P2 |. O索引名称索引类型唯一性EMPTEST_AK1NORMALUNIQUEEMPTEST_HIREDATE_SALARYNORMALNONUNIQUEEMPTEST_PKNORMALUNIQUE
  p9 n" [. C+ o3 H  EmpTest表还包括六个约束:9 t" G, p' J* {* d' W
  I& {+ u2 ]1 ?$ [
  · 一个主键-EmpTest_PK
3 |8 y1 h# M' e! j4 v* N( m
# p. {3 b. G6 u" Q3 r  · 一个备用键-EmpTest_AK
+ S! Y/ @2 g" F: l7 a2 I7 f
1 g: x8 Z8 L2 [: o  \  · 一个检查约束-EmpTest_CK1 ) x4 W' N9 \1 P8 i0 L: l
+ V" Y/ m3 p& f% A: G
  · 系统生成的(SYS_*)三个非空的约束,名称如下:
# Q/ r+ Y! T: z; W% Y% l9 Q7 X1 `! `  D& t1 f& y
约束名称约束类型索引名称SYS_C002144065C  SYS_C002144066C  SYS_C002144067C  EMPTEST_CK1C  EMPTEST_PKP EMPTEST_PKEMPTEST_AK1U EMPTEST_AK1
" v. H) p6 A9 S9 o* N  现在我们执行匿名的PL/SQL代码块来调用DBMS_METADATA.GET_DDL函数,检索数据表的定义。5 z5 ^; l. b8 K' _' u: f1 u& y
# t9 F; O( D9 [9 V
  DBMS_OUTPUT程序包只能输出最长为255个字符的字符串,由于在处理数据表的DDL字符串的时候太容易超过这个限制,所以这是一个问题。为了解决这个问题,我们使用了本地过程Show()(列表1所示)。
回复

使用道具 举报

 楼主| 发表于 2012-8-4 14:06:20 | 显示全部楼层

Oracle中提取和存储数据库对象的DDL

列表1:调用DBMS_METADATA.GET_DDL()函数的PL/SQL代码块# D& S! d1 E+ E! v3 M& A

  ~6 [, P" Z' M2 W4 Mdeclare2 B+ ]) C" K: V2 R# f
vClob clob;  e* R) \2 z! O/ A7 f9 _8 l# u' r- a
vLongString varchar2(32767);' @1 V, b4 }  B4 V3 J4 m
vOffSet pls_integer := 0;0 k* d. M. I; H$ {" D$ p; E
vLength pls_integer := 0; 4 Q  o6 c, e: g
vTable varchar2(30) := ’EmpTest’;
1 K3 c& I/ d/ U0 `- ?. y' P/ I
3 @" L# D" c, u$ h" `& Xprocedure Show (pVariable varchar2, pLineSize pls_integer := 80)( q- x& U( ]5 K4 v& X3 S: T5 Q
is
- S! V! [$ e3 F6 w! Q1 obegin
+ v: `2 Q3 ]  u. a, J3 g3 wdbms_output.enable(1000000); - c3 q" Q- S. }
if (length(pVariable) > pLineSize)
) y6 j6 {! R4 h! [( o8 g! o6 Wthen
! x9 [6 l$ [% g5 O4 d8 bdbms_output.put_line(substr(pVariable, 1, pLineSize));) M1 n/ a9 o8 @: x+ D" E! k& _) a- G
Show(substr(pVariable, pLineSize + 1), pLineSize);
( a" l- k9 b2 ^& Z9 _& \/ kelse # z+ k( q+ V- Z1 V) @% u
dbms_output.put_line(pVariable);0 |8 m; d% L* D& M! N1 g7 P# b) c
end if; 7 T, K- R  @$ h1 s- ~) v5 k
end Show;
1 p" x% ]$ v7 m% @0 ~begin
8 c$ v9 i4 N2 V9 }4 \-- 获取 DDL3 g; Z: B! @; Y, A* R
vClob := dbms_metadata.get_ddl(’TABLE’, upper(vTable));
2 N6 I7 ^( S1 h% X& G- w3 a+ ^4 `
0 k0 L' a- R5 w( ?-- 获取 CLOB 长度+ J5 A3 O7 ?. x% g
vLength := dbms_lob.GetLength(vClob);
7 q- k) T% T3 G' r% l: [, ?; Ndbms_output.put_line(’DDL length: ’ || to_char(vLength));
3 j' E8 M( n% s$ i7 ]! r
0 Y8 b! e* A" S* T; h, TvOffSet := 1;+ X; G# C2 A# r2 t# D8 ^; u- w% g
dbms_lob.read(vClob, vLength, vOffSet, vLongString);2 L3 t! n4 ?& r' a  B
-- 关闭 CLOB
9 ?6 E# z8 Q+ _& Iif (dbms_lob.isOpen(vClob) > 0)
- \! ~; S# {6 E5 }then
) d( B9 o) L' h! \/ _8 I7 C. edbms_lob.close(vClob);
# i: ?, q5 Y/ R  \- ~* G% qend if;
9 k3 r7 d0 y& kShow(vLongString, 80);
( o0 P( I" K, E! V* zend;, D, T. q& l- S  j6 n
  列表1生成下面的输出信息:
+ d3 E5 `7 T0 X$ f9 U; r6 G) {9 [, L4 }+ I
DDL length: 461
, n6 R! m) r) r" Q; t2 tCREATE TABLE "BORIS"."EMPTEST"
* \6 Q$ w; f) w# _: |* n( "EMPNO" NUMBER(*,0) NOT NULL ENABLE,
  Q7 d* b! U* U" }; n"LASTNAME" VARCHAR2(30) NOT NULL ENABLE,
4 y' C( q+ y9 {6 @# @6 r"FIRSTNAME" VARCHAR2(20) NOT NULL ENABLE,
! \1 ]! f2 e' W% c' ]3 n"JOB" VARCHAR2(9),
' b! a' _! H6 J2 Y- c7 @"HIREDATE" DATE,
, b# N7 X" y1 t8 X"ISACTIVE" NUMBER(1,0),
5 |# g0 D9 \: z& ?"SALARY" NUMBER(9,2),
8 a. F' N( |: Z/ |2 M+ g0 l"COMMISION" NUMBER(9,2), 1 n5 z, `# ?0 l4 o1 t$ ~" i
"DEPTNO" NUMBER(2,0), 2 I( _& }! t( e( ^  j
CONSTRAINT "EMPTEST_CK1" CHECK (isActive in (0,1)) ENABLE,
" T& t, e. \/ x3 zCONSTRAINT "EMPTEST_PK" PRIMARY KEY ("EMPNO")
% W. w. }$ o  X4 n& v& Q* mUSING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 - m4 ]" g9 N) Y6 z' m- m! `* Y) P
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
- [5 n1 @/ s2 s! i/ F9 x( xPCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
) ?( h  B9 L7 U" wTABLESPACE "TOOLS" ENABLE, CONSTRAINT "EMPTEST_AK1" UNIQUE ("LASTNAME", "FIRSTNAME")7 a/ E+ W, U% {1 D. T7 v& |7 s
USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255
: J. Y, T( ]: U4 K' MSTORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645! S% A' n) p- [- J# E0 i5 L( e" Y5 O
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
3 ^+ J8 E: V( d- ]5 h; LTABLESPACE "TOOLS" ENABLE) PCTFREE 10 PCTUSED 40 INITRANS 1 6 c0 d- k% B; j4 T; U1 b
MAXTRANS 255 NOCOMPRESS LOGGING0 I8 y6 v* n& L* t, \
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645) e3 ^3 Q& i; E9 `; E
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)* ^4 }6 a' e; j2 e
TABLESPACE "TOOLS"
; R8 o  o; G/ X6 Y& R4 K  它运行的情况太好了,返回的数据表的DDL字符串带有主键EmpTest_PK、备用键EmpTest_AK1和检查约束EmpTest_CK1。它建立了两个唯一的索引来支持主键和备用键约束。这不是你需要的结果:你需要一个表,但是为了加快数据载入速度,它不要包含约束和索引。只有在数据载入工作完成以后,你才建立索引和约束。
" X  v' D- h$ W5 g1 c) F% f, i/ W5 w7 F$ J
  保证对象的定义独立的另外一个原因在于灵活性:你可能需要改变对象建立的次序。
$ Q" B) c8 u: ?$ Q* m# B( w/ S/ t2 K$ N* L7 b; u4 J/ W) r- c; A; a! @: @
  现在可以设计一个数据结构来存储对象的元数据了。# p* ?+ N) o1 H5 ^( x# z3 h

, L3 z1 O4 a7 `  \( |$ [2 W5 K8 }  元数据存储器:MetaDataPkg程序包规范5 `: \' o6 e  O: V# B# L' T/ {! K1 r
/ w$ H+ r9 _" `6 }
  首先,你必须建立记录类型来存储独立的对象(例如数据表、索引等)的所有必要信息:" O+ O# q5 C# a! G; }

1 ?$ U% h9 k3 E2 u( ~" @subtype tString is varchar2(30);
0 y; R, ?- ~! d5 usubtype tDBString is varchar2(255);
) @/ D" l/ I1 n8 dsubtype tDBLongString is varchar2(4000);/ n1 I- c; ?, n: f8 g
subtype tLongString is varchar2(32767);4 [5 u, Y8 R0 q6 q* y- V% o
type tArrayLongString is table of tLongString2 @% @1 M, T1 [% J+ n: n2 x: w
index by pls_integer;
6 [! Z) l, D5 y8 D9 stype tMetaObject is record
. r% m% Q6 m7 W" m(7 P4 H! g6 W* G: d3 U+ U
aName tString,
2 u8 y$ k6 y) @/ yaType tString,
( N/ K+ r6 A# ?  OaLogging tString,. ]4 Y/ L5 b* C- g8 |( v9 Q
aParallel tString,
" k- `; E6 Z( E6 e- z; NaStatus tString,) j! d. I) M8 D* h6 F
aValidated tString,
  W7 w2 A" K+ W3 X7 e/ GaRely tString,
+ s" s2 U2 Q  X7 W$ r9 |aDDLString tLongString
( S* p/ U  |' d; J2 h# \' Y);
% t$ O  k0 b6 d# c3 H' @  s8 O  tMetaObject属性保存了下面一些信息:
# W4 b% Q0 L/ w, @
- K$ w, A1 d9 A  · aName:对象的名称,例如EMPTEST_PK1。4 h, I0 V& O" k/ \, k5 X

# _& a( y/ y. s' [7 m  · aType:对象的类型,例如’YES’ (分区的)/’NO’ (分区的) (用于表)、 ’UNIQUE’/’NONUNIQUE’ (用于索引)、 约束类型 ’P’/’U’/’C’/’R’ (用于约束)。
! b; P& U$ K4 M% B7 W5 O
+ r9 X) G; A4 g/ y! }  · aLogging:对象的日志选项,例如’LOGGING’/ ’NOLOGGING’ (用于表和索引)。
) w* {2 o6 o. B- q
1 x/ Z( I  Q) C  ?  · aParallel: 对象的平行程度(用于表和索引)。
8 {( e4 `, `2 I% \* x  u7 y4 s( \
9 L0 Z$ ?$ ^1 a, q$ _& O7 E  · AStatus:对象的状态,例如’VALID’/’UNUSABLE’ 用于索引、 ’Y’ (备份了)/’N’ (未备份)用于表。
2 h9 \$ O8 X! d! S& R1 ~* b4 l3 }! m& m4 g( z
  · AValidated:对象的验证选项,例如’VALIDATED’/’NOT VALIDATED’(用于约束)。
; N: w* I. W6 r% _8 M  L2 h% X
; ^% I- q6 N, f$ F6 ]( B  · ARely:对象的依赖选项,例如’RELY’/’NORELY’ (用于约束)。
  o+ {2 n4 F& r( L  |% l  b7 K6 G! K3 ~; s+ k" Q
  · ADDLString:对象的定义SQL字符串。8 G# y% O' c/ l( P- m( [* X

" @4 v. M! j* y; A9 n  现在你必须定义一个相关的数组类型,它能够列举出某种类型的对象,从保存tMetaObject类型的多个对象,例如,所有的EmpTest索引:# m/ L! V8 [4 m( v$ t! o
; [  w. c+ v( C
type tArrayMetaObject is table of tMetaObject/ h: _1 Z& i, z0 @0 C/ i2 l
index by pls_integer;
) K0 V4 I. D5 B5 H  ?, q8 I, ?  下一步需要建立一个记录类型,它包含了数据表表自身(aTable)的tMetaObject属性和三个tArrayMetaObject属性:一个用于索引(aIndexes),一个用于约束(aConstraints),一个用于触发器(aTriggers):: e/ v0 g- Z% c1 K* Y
  w  Q' p7 r6 O4 G: x! [3 x
type tFullMetaObject is record
# w/ T1 @$ w" }# O(
( g+ Y, M: {6 f. E7 H$ h0 E3 c. yaTable tMetaObject,! ~& p3 M7 l$ \  _: y+ c
aIndexes tArrayMetaObject,
% \2 M$ h* V) @' PaConstraints tArrayMetaObject,
* U6 S! o3 Y9 q( h! OaTriggers tArrayMetaObject: t) f; e+ h+ [9 O) m5 u" C
);- R5 C( \; K- `. g) V- |4 f! x; V
  tFullMetaObject对象类型保存了单个表的全部对象的元数据。最后,位于顶层的类型是tFullMetaObject数组。TarrayFullMetaObjectByString类型是tFullMetaObject的一个表,索引类型是varchar2(30)。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-8-4 14:06:21 | 显示全部楼层

Oracle中提取和存储数据库对象的DDL

列表2:MetaDataPkg程序包规范
- H( b' V, c. V0 M; ^/ d1 K2 W2 y( _3 v- h6 l* f
  用如下的方式建立或更新MetaDataPkg:" ~( Q- c0 k; b$ x% U6 Z
8 U" w) L, ]3 I( Z  z3 n
cEnabled constant char(7) := ’ENABLED’;
( m: @  F8 @3 t. McDisabled constant char(8) := ’DISABLED’;
" g9 C' v. E; h; ^6 k" _cUsable constant char(6) := ’USABLE’;3 I! A; V3 Y& q# [( e( E" k
cUnusable constant char(8) := ’UNUSABLE’;
" J/ B; e. R. i) z$ f* BcValid constant char(5) := ’VALID’;" F7 H- k& b) v. S! P
cInvalid constant char(7) := ’INVALID’;& [# x1 F) ^3 l. @
) ^  w' E: X4 N& R5 M' j
cTable constant char(5) := ’TABLE’;
% |" J/ f8 [4 `cView constant char(4) := ’VIEW’;0 X9 u! p" f) P7 c$ \5 l
cIndex constant char(5) := ’INDEX’;
5 E8 _: {3 Y' H% h) y4 k6 RcConstraint constant char(10) := ’CONSTRAINT’;& n9 u3 _9 p" S( j* A% E5 x0 _
cTrigger constant char(7) := ’TRIGGER’;
. D  ?2 F( A. W) l# D. qcLobType constant char(3) := ’LOB’;, T* Z8 L3 S! l& [( f9 S' P! Q, f
cClobType constant char(4) := ’CLOB’;
0 |, g# k8 s/ }) X7 J0 jcBlobType constant char(4) := ’BLOB’;! h$ \$ }5 S; F; E7 a
cPackage constant char(7) := ’PACKAGE’;( V* f# ^' z+ u" H" t
cPackageBody constant char(12) := ’PACKAGE BODY’;7 Z9 `( l# u: \! v( v- [# I
cProcedure constant char(9) := ’PROCEDURE’;
0 Y7 F, r) J" X' n8 {cFunction constant char(8) := ’FUNCTION’;
( R/ J5 V! ?4 y9 \& LcSequence constant char(8) := ’SEQUENCE’;, P( V! N3 Q# w5 W" }8 P$ m# O
cSynonym constant char(7) := ’SYNONYM’;
1 t+ `- i' F% h: K. `  _/ rcType constant char(4) := ’TYPE’;( T5 X* u5 G5 L8 i3 J- U2 T
cColumn constant char(6) := ’COLUMN’;
3 R: r4 P4 t% ?% p: A5 F& H! d: \cJavaSource constant char(11) := ’Java SOURCE’;
. w: X6 _3 I, |& r; O. WcJavaClass constant char(10) := ’Java CLASS’;
+ S+ g, x8 y( r* z5 a
3 y4 o3 c& c, r5 Q3 ~- rcYes constant char(3) := ’YES’;8 m! [8 k) i: {# e2 X# _5 b- B
cNo constant char(2) := ’NO’;
" y+ [4 g; w) Z4 [
# q% f- P* d9 [# KcPKConsType constant char(1) := ’P’;
' Y9 b4 N! `8 ?, NcUNConsType constant char(1) := ’U’;. J2 g( o$ Z& [4 O) Y% q' l/ w
cFKConsType constant char(1) := ’R’;
6 E$ Y4 K' M8 m  G8 r& qcCKConsType constant char(1) := ’C’;
$ o: V4 J# k& i* G8 Y; P$ i" J3 ]- ^6 c$ W; Y
cDropStorage constant char(12) := ’DROP STORAGE’;
7 [  N/ D* M; FcReuseStorage constant char(13) := ’REUSE STORAGE’;
1 ^: P; R; `% M+ i' S) P: ~cCascade constant char(19) := ’CASCADE CONSTRAINTS’;: D0 s2 f7 j! [5 \6 H4 S8 B
cNoCascade constant char(10) := ’NO CASCADE’;
# X# g: s' K! i, i9 VcEnable constant char(6) := ’ENABLE’;
; Z1 u! g9 i" W; `9 |6 A! VcNovalidate constant char(10) := ’NOVALIDATE’;
2 }/ }0 [3 \, J4 U# B* ycRely constant char(4) := ’RELY’;0 d: v& N4 g. U# T  Q, T
cNoRely constant char(6) := ’NORELY’;
. r9 K$ V/ V+ K( HcValidated constant char(9) := ’VALIDATED’;4 }( E3 S" U% z8 T  o
cNotValidated constant char(13) := ’NOT VALIDATED’;! W, _2 X- M! b7 k1 y0 Z. k4 K
cLogging constant char(7) := ’LOGGING’;& V+ P# \4 {4 S9 h2 i
cNoLogging constant char(9) := ’NOLOGGING’;
  o+ t  c7 K- y8 W+ U7 ocParallel constant char(8) := ’PARALLEL’;
# V/ U( [9 x. E% P" k- N% scNoParallel constant char(10) := ’NOPARALLEL’;
9 M5 d# ]7 D4 J+ g& W4 _, S: I( \cNull constant char(4) := ’NULL’;5 Q4 ^' I' U) ]8 @8 l" e$ Q, r
cNotNull constant char(8) := ’NOT NULL’;6 X) b0 e9 @( w1 X. }' }
cDefault constant char(7) := ’DEFAULT’;6 \' S. R% ^: x" r/ r+ G

) S' g, q# U! I. A* f1 |cSYSPrefix constant char(4) := ’SYS_’;2 t  S- a- q5 M, {$ C+ m# h1 u: |4 x
cDoubleQuote constant char(1) := ’"’; 1 G1 ^5 W! w4 n: H5 `' C- f
9 E; @. N4 ^! M/ w$ Y
subtype tString is varchar2(30);& }% J% {, C! _0 a0 |& R
subtype tDBString is varchar2(255);
- K1 w$ D+ u4 a& c- c3 X6 \subtype tDBLongString is varchar2(4000);" C5 Z+ _: x# h  H0 q% i) q
subtype tLongString is varchar2(32767);   z9 v5 w. R0 b- _, z
. e+ I5 r4 p0 {4 v  b0 P; b3 p
type tArrayLongString is table of tLongString
. x8 Q8 R7 W6 D& aindex by pls_integer;& @5 @( C; E2 b; q1 Y( L* ^- K, t; K' o
# t9 s3 u# T; C  G5 G: T$ c
type tMetaObject is record
# I% J" Y; Y$ q- [(* h7 A, ^+ x. ~1 b$ [
 aName tString,
4 U# P7 t/ }9 [2 l aType tString,
) Z! e2 _4 R% @" g; k aLogging tString,4 n  ?3 A& k, B/ j8 ?. c$ r" K' R
 aParallel tString,* G* D* z7 D8 Q3 ]3 X+ i( ?7 p
 aStatus tString,
/ u5 W6 T) X6 U$ H9 k3 q aValidated tString,
3 [; F5 H) \6 @1 y) B9 [$ P' z2 G aRely tString,/ a' S% M) b" e5 }# ]$ O& ~
 aDDLString tLongString
' ]4 \$ L" C( \# c& @  u' [);+ B" J6 `+ }9 `/ M9 x1 |3 @

* y* `# a) y# m( wtype tArrayMetaObject is table of tMetaObject: K; @" M# ]; Q. I" [1 V; O
index by pls_integer;0 H1 x% g: G0 t+ i$ h- P
# l" i5 L* h# t( e0 ]9 w1 m
type tFullMetaObject is record
& q3 ^- D7 x4 W5 |(, \- I) a3 [% R7 U5 `/ o
 aTable tMetaObject,  C/ ?5 o- I: Y& m7 Q" X! z( q4 Y. n
 aIndexes tArrayMetaObject,
- i: g% q  D, z. J& { aConstraints tArrayMetaObject,' F/ s' a7 V' L5 g! i
 aTriggers tArrayMetaObject
4 ~1 O& O, @6 _1 e$ T  k; ]& ^);
" c. m- D0 L! H# S5 L6 {5 u+ K* R+ ^& s/ j3 a/ k) {, \; q; `& H
type tArrayFullMetaObjectByString is table of tFullMetaObject/ i; n7 C% B, L+ s
index by varchar2(30);
% ?! f! a5 P! r4 f" ~5 C9 k. X5 H. w/ V; M
procedure Load
1 i% p% H5 `' Q/ S(
3 }  ]3 ~  Y, p5 B. A: T1 R4 i pTable in tString,
) A; Z; l/ F7 E, n& F pForce in boolean := false
/ f& n: y+ u; L8 w, r6 R% G& j);) a" t* G% @8 a3 ^( ]+ i% \4 n" \

% h8 S' v( z/ W6 v3 g# Bprocedure Reset
$ w1 d# H- P8 g. @: r  e(, _" Y! R+ E5 k% O# d
 pTable in tString
) m( o( @9 ]( x# R, r6 [);* R! W6 I  O  g+ g. y0 W  ~
" h. s5 R/ [$ |1 [! E3 _, V8 B5 {
procedure Reset;
& B  ]7 P5 \" ]& j; Y: r/ V- D& P+ R- S/ m: b3 W; t2 O6 C
function GetMeta3 ]: y5 X  C( `* n  G2 F
(
" [; V5 |+ o1 _7 l! y+ B" [- A6 M8 w pTable in tString,4 T) B( e- A- C: ~4 t, E7 V, v7 ]
 pForce in boolean := false
6 ?8 f6 ]! f, b& B)
3 g, a4 _% P/ H$ x8 H& I8 j7 ]return tFullMetaObject;# }8 n  T& H, d: ^; H( Z

# N# o! i0 M& d: @0 cfunction GetMeta
( K( i  W0 A& Greturn tArrayFullMetaObjectByString;0 t: ~1 r4 f7 T
1 Z( q2 Z& _9 A! m- g
procedure SetMeta
$ n  S2 G" f: C* j8 Q(
' K# A, c' n7 g; m/ H  t$ S0 U pTable in tString,2 k2 V( I7 \$ i0 a& V8 w' I. L
 pFullMetaObject in tFullMetaObject
# n& A+ O! u9 V! w3 N# a" C);
$ F1 E* Q+ A# J0 R* g+ I: }7 p! r4 i! R4 b
procedure SetMeta/ D2 o0 b  l0 _) Z8 }9 d( t2 P
(
% O) u% k9 v, u( P/ h2 F pArrayFullMetaObjectByString in tArrayFullMetaObjectByString
9 S4 c! e4 S; u);
3 m' C1 [9 C' Y8 i( y+ e0 M' J/ `' r3 j3 E2 [
procedure Show 4 I8 E5 ~  m* H, [( |
(+ W# S( q* E$ W+ ^8 W
 pTable in tString
+ j, o8 x$ ~  u);5 W( ^! A8 }6 x4 B) s4 ~; z

) X- n2 A7 b0 r9 Zprocedure Show;
1 @; E$ i5 S  \end MetaDataPkg;
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-8-4 14:06:22 | 显示全部楼层

Oracle中提取和存储数据库对象的DDL

上面的类型对象是作为元数据存储器的,用于存放多个表的完整的元数据信息集合。所有上面的类型都包含在程序包规范中(列表2所示)。我还介绍了下面一些API:/ a0 w. `) S6 P1 l& p: T

3 z& D3 h) R+ o+ K# h) v  · MetaDataPkg.Load()过程:把特定表的元数据信息载入存储器中。
& m8 X, H$ d  Y% w6 m
3 `- H) @, e8 J" @/ d- i4 r  · MetaDataPkg.GetMeta()函数:它从存储器中检索tFullMetaObject类型的对象。
! `* E' z; E: e; ~) q. Z# S3 s; P0 M. b( i
  · MetaDataPkg.SetMeta()过程(重载的):把对象的元数据存储到存储器中。 3 ^5 H' _6 K* r/ X
- z4 k$ O. X' ^3 j1 ?8 P
  · MetaDataPkg.Reset过程(重载的):对存储器复位。
, `) z. Y" H3 F! u* z; `, i, B) U' v& |8 d" u
  · MetaDataPkg.Show过程(重载的):显示存储器的内容。7 _5 W  f% Y9 }$ o8 c) q2 S4 y
( d# z. D* Q7 c! P& [& [" m
  实现所有这些事务的代码
7 Y! ~5 ]! K' g6 P) R2 a% U- p/ o
& o2 u& E; T1 D; L  列表3显示了MetaDataPkg程序包主体代码的一些解释。私有过程SetEnvironment()包含了所有的环境设置代码。在程序包的初始化部分会调用这个过程,因此在每个对话中它都只执行一次,符合你的需求(你希望在开头设置一次)。程序包提供了用于设置环境参数的API:DBMS_METADATA.SET_TRANSFORM_PARAM()过程。/ n, W1 L6 b2 P% [5 N. q

) H/ v/ y4 J- L  列表3:MetaDataPkg程序包主体
8 ]6 ~  F. E1 X
2 S$ K$ i% ~# m2 M$ k' Y* C, I4 t6 `vMetaData tArrayFullMetaObjectByString;
; v4 ]( Z$ r" L% L% c+ z/ O* P8 g9 i  A$ l. s( s
procedure SetEnvironment
, }, n+ z1 f5 s3 q4 g; Wis
5 W- z0 C2 P& m$ p6 Fbegin
, w0 `; m1 p6 C) o: P) L dbms_metadata.set_transform_param(7 l1 X, ^2 q! A) G
  dbms_metadata.session_transform, ’PRETTY’, false);9 z* [: Z0 ]( [
 dbms_metadata.SET_TRANSFORM_PARAM() u/ `5 K0 Z2 i% V. F& ^5 s: R! @
  dbms_metadata.session_transform, ’SEGMENT_ATTRIBUTES’, true);" m% p. I" U+ w
 dbms_metadata.set_transform_param(6 S+ x: Q* Z. l4 N, V
  dbms_metadata.session_transform, ’STORAGE’, true);4 v, k& a- [! e3 m
 dbms_metadata.set_transform_param(1 k) w) v6 f- ^/ e) z" k5 ^4 _
  dbms_metadata.session_transform, ’TABLESPACE’, true); 3 I  H6 C7 Q( N% W$ \! z* |
 dbms_metadata.set_transform_param(
* Q. S: T5 ^$ w2 G# L" n  dbms_metadata.session_transform, ’CONSTRAINTS’, false);! N. }3 R% H. G$ p1 l0 u
 dbms_metadata.set_transform_param(
' m5 q1 z: Z1 [& C  dbms_metadata.session_transform, ’REF_CONSTRAINTS’, false);4 u9 \, o- i# {% }4 \/ b' ?
 dbms_metadata.set_transform_param(' o, d& r  K. h1 I
  dbms_metadata.session_transform, ’CONSTRAINTS_AS_ALTER’, false);
2 `1 X) w5 o; I3 |: J! M7 C% w' ~
$ v7 g* ]. @, d( u& Uend SetEnvironment;; l. t/ d" J3 E: J& r

- G7 k+ V4 T, e9 |procedure Print1 Q7 A2 G4 z7 q" ]3 ?+ z
(* {. k5 C4 N+ m, D) h
 pString varchar2,
/ D2 k: R/ f; v pLineSize positive := 80
+ y: z3 p* E1 T) S9 F)
8 t3 I4 K  _6 d2 His
" w' Z) ?2 j( b3 s% g# ?' z4 |& K/ ^0 A: s% ^% g" t
vLineSize pls_integer := least(nvl(pLineSize, 80), 255);6 o" {1 J' _& J$ a+ [6 Q+ n
9 _4 t1 r) u9 |- F- V
begin
; I! Y; d& W0 |# K7 @; J dbms_output.enable(1000000);6 w1 \: n  `3 m! B- P* l; `* V6 a
" ~+ z2 l8 }; K. J( I1 q4 s
 if (length(pString) > vLineSize)
" S( i# @; b7 l4 y( r. S then
8 R2 j) M, `. l1 |6 r7 p  dbms_output.put_line(substr(pString, 1, vLineSize));
5 F4 C( y$ a1 p# c! D( x7 z/ s  Print(substr(pString, pLineSize + 1), vLineSize);
& c- ?- h2 C  K3 B else  d8 o" _( J* r. r( s* u+ H
  dbms_output.put_line(pString);4 |: `$ f( M# D& [9 a
 end if;; p7 Z7 |3 W# F  N! I; G# J

5 B2 {8 D% d. b6 Bend Print;
  T' ]6 ^5 H# K. U! D
' r! p$ x0 g4 h! H& c  G4 D" Dprocedure Show
5 h- T5 |; {9 z" T. A(! ?3 Q/ f3 k$ Z" y
 pMetaObject in tMetaObject: x3 f+ `0 N/ J9 w! q, ^% ^9 F8 b% K
)) Q5 u' {8 D' T  {6 l9 `
is
" t8 M+ D7 m8 O" s& Ubegin  o' v3 x$ ^5 r& ~% j) A' d4 ]
dbms_output.put_line(’***’);
$ M1 j8 A' I; ?1 P  r! kdbms_output.put_line(’Name: ’ || pMetaObject.aName);5 d' U5 Y+ v1 ?2 H0 k/ @1 m6 F
dbms_output.put_line(’Type: ’ || pMetaObject.aType);
; x  T6 ^3 G1 S9 p4 q1 B. Cdbms_output.put_line(’Logging: ’ || pMetaObject.aLogging);
* R5 B; T% t2 p  \" ]! M: M1 sdbms_output.put_line(’Parallel: ’ ||) j9 G: ?0 M% m' E3 m
to_char(pMetaObject.aParallel));
: a( G7 M/ D8 O  Sdbms_output.put_line(’Status: ’ || pMetaObject.aStatus);
0 U( i: r! G# \2 Gdbms_output.put_line(’Validated: ’ ||
# T5 ]  e3 v5 r0 l- j0 h, N  _/ N: z3 lpMetaObject.aValidated);
4 M1 c" i  d) Bdbms_output.put_line(’Rely: ’ || pMetaObject.aRely);
( D9 Y, o& S- \  L4 [5 nprint(’DDL String: ’ || pMetaObject.aDDLString, 255);6 Q" n; C7 S+ ]; @& E1 y; Y
dbms_output.put_line(’***’);
# F/ t( K0 b" o8 ~- h' z$ ~  A2 a, Tend Show;
: a( e. @! r# m; B& U& A; r
6 ]$ @$ \0 V" @& N* C: cfunction GetDDL
$ P7 G+ B$ t7 ]8 ]- `, x2 m(
1 Y( Y) m9 ]* s% z( Q6 ~" ~ pName in tString,
) C8 b' ~$ H. X$ W$ }# d' z$ ` pType in tString0 |2 m% G  @% V( h9 p. l
)  i% A0 L" \2 O; p" b
return tLongString
( C! Q  S' ^6 S( Xis
# ~  z3 p, N" z2 s8 cvClob clob;
+ f- C) m$ M1 B; C( O' ~
* H% H# }7 W2 L5 W( g4 v3 _- ~  pvLongStrings tArrayLongString;
# v" Q: x6 r. v- r/ U+ `$ [' ?- c
vFullLength pls_integer := 0;" g  Z8 Q; r% ?& h: r, h' B" y- O% j
vOffSet pls_integer := 0;( A; \. }* a+ D+ J  R0 B$ w; x
vLength pls_integer := 0;
# I3 E$ j. i5 @8 _6 F
9 T$ o% q; _; E. b- k; J4 d8 rbegin
. f  e6 T* R# w3 B0 m& D( d9 ~+ u; i, {4 T4 v9 }# B
vClob := dbms_metadata.get_ddl(pType, upper(pName));
6 b8 ?4 J. V4 m4 L9 t! B  Y
4 J8 _8 v! ]- JvFullLength := dbms_lob.GetLength(vClob);* o5 C& h- n* B# g

2 A8 ]8 ~7 z- z4 ^1 U9 V8 Mfor nIndex in 1..ceil(vFullLength / 32767)  S5 ?# B4 t: n7 A* w4 B
loop
- E# U- n- h6 H6 |2 r vOffSet := vLength + 1;. K8 i4 Q, ~& z( q# M
 vLength := least(vFullLength - (nIndex - 1) * 32767, 32767);8 p8 h: D1 w1 U( v: V& w
  p; {$ y% B/ n) P) \3 I6 I* o& J- R
 dbms_lob.read(vClob, vLength, vOffSet, vLongStrings(nIndex));
. l$ K2 A% I# M( d+ Z/ Y2 t$ @! @; z) X9 E, c+ L6 Y5 K
 vLongStrings(nIndex) := replace(vLongStrings(nIndex),
7 G8 Y7 l; K& p, ^  ]- G1 v9 G" p" m3 h    cDoubleQuote || user || cDoubleQuote || ’.’,% U# ~7 j7 n: M8 B) t- B0 B
    ’’);' Y6 K* E& C: Q- m' ^9 D

) `2 e0 ~/ p2 |5 l2 F. ? vLongStrings(nIndex) :=ltrim(rtrim(replace(vLongStrings(nIndex), chr(10), ’’))); $ ^: m/ E7 {! T! g
end loop;
' R, ]1 R/ c) t% U/ T$ [4 W- q* s! O' q% X
if (dbms_lob.isOpen(vClob) > 0)
3 c" y9 m+ |% U% Q4 |6 ~& q/ `- Athen
2 d/ g6 ~) q( P8 ?+ ] dbms_lob.close(vClob);# g, `5 u1 _4 s
end if;" ]$ A0 s0 g4 h7 X; S
- I3 M; r. r: h$ ?- O. z
return vLongStrings(1);
9 X3 @8 c* z5 u! i9 M7 _3 i: v! [& B8 e' ]; g
end GetDDL;
: F1 J  z2 E2 _' C) s" Y; O' X. ?$ h2 b  j8 a- H
function ObjectExists
& n7 ~, a/ Y; Y# e(
4 x( x" `/ B) Y; w pObjectName in tString,/ q7 {4 Q$ ]% P5 J* Q
 pObjectType in tString,$ F; T! l8 v! L8 g
 pTableName in tString := null2 d" g; h! n$ b2 x
)# s' S. z9 `( W; U" c- u
return boolean  Z8 U8 ^6 G- D# v: M  U" e7 A; K
is; _+ P7 R0 _7 b0 p) ]5 X' B
# p, e* b* h& @9 e& O( _
vCount pls_integer := 0;
) a9 d0 p' {# A  qvObjectName tString := ltrim(rtrim(pObjectName));
% w4 D' e# r9 G; l; L9 K- D  TvObjectType tString := upper(ltrim(rtrim(pObjectType)));
2 h+ A6 C1 w7 {& E: X; ]  z" mvTableName tString := upper(ltrim(rtrim(pTableName)));
( |. C8 S' f7 D. q8 Q# C
: v, }  L! k( v6 q" Pbegin& A' j% K; G7 s; A* ]6 G

& X  u# I. B9 S% [* Y3 b! Mcase! a0 X: A/ s/ @" l, K) a  Q9 e
 when vObjectType = cColumn
6 N3 @& I0 m% }- G) P! e& ]8 I9 ` then' V9 |$ e" t: ]+ q2 N9 E# v
 select count(*)$ E3 `! b7 W& i
  into vCount% ^" z' J0 j- m- m" o0 j
  from Dual
9 a2 J8 d, t9 g, G6 O  where exists (select ’1’1 k7 ~# J/ c  ~% X
  from user_tab_columns% T2 b. |& l) V0 c% M1 K
  where column_name = upper(vObjectName)8 F# R+ r! Y4 q) o: p
  and table_name = vTableName);
9 s+ A' t5 R8 E8 O4 n! T: g1 K8 g8 H5 E: a/ \) `
 when vObjectType = cConstraint
" i* O/ Q5 w2 N; |6 P5 Z then) [7 h$ n* a0 `
  select count(*)
, l- |  S9 o+ F* V# q  into vCount( Q; N/ @5 F# O1 [$ k
  from Dual
* F, {$ K) A7 R/ I3 y& y& W  where exists (select ’1’+ x; K) A9 }# }
  from user_constraints2 \8 U2 W% G, B9 H3 m$ d
  where constraint_name = upper(vObjectName)
% q% l0 D! L! l/ J) R& W  and table_name = vTableName);
- e! W4 T# e' ?+ T
1 }, \; n% R6 E$ p5 p8 mwhen vObjectType in (cJavaSource, cJavaClass)0 C4 ^- S# f5 L0 w: N7 n
then# D2 ^1 x6 E8 Q5 [. N
 select count(*)) o5 j9 `+ N  ~: V% N/ W3 Z! c' P- U
 into vCount
  A( Z7 Q9 G& P- k( s  s: p9 ]# g from Dual
. S5 U+ b& _7 X5 G* C7 _ where exists (select ’1’' L; J1 W9 `; X5 u
 from user_objects. U0 b: @3 Q6 h$ j
 where object_name = vObjectName and object_type = vObjectType);' {& k- }1 _  `# p5 G1 O

8 M8 f4 f' y: N  j3 z else7 r. I& e3 X: a+ ~; Q9 U4 ?" j
  select count(*)0 s# l% Z) n! f6 F& M5 E
  into vCount9 l  M. N* E; c3 h5 o" D. M# y
  from Dual+ G4 o) ?. w0 K& p" ^
  where exists (select ’1’- P' {" B* O8 q* q2 Z! q9 M
  from user_objects- v  T! ~% R; E2 T+ c
  where object_name = upper(pObjectName)" z4 T: ~' q7 `" h
  and object_type = vObjectType);
- p  T( T2 J" M* C. g end case;1 e3 t# Z. R! X! ~% M
1 N' ~. ~. e! w
return (vCount > 0);8 {) B: t' j" s6 S8 t

+ A% S7 ~2 z- Z# xend ObjectExists;
/ Z, o$ J" C' ]3 _6 z' b
) @3 f$ f& M& z7 D' w1 a+ t8 Mprocedure Load
7 t0 m# J+ d1 f) x(
4 {- N. p* g4 X  J7 N' v# C pTable in tString,
! C: W/ Q0 v8 }5 A) u/ w pForce in boolean := false- \. p& l( `1 a
)9 g/ ^8 [* K. d0 y
is+ [% [, N% D7 [

5 [- A3 [" F9 B3 `, GvFullMetaObject tFullMetaObject;4 D% [; p" `4 |! e9 Z' N

/ G2 X- @5 Z+ K# O; R( W3 {vTable tString := upper(ltrim(rtrim(pTable)));0 K, K- {  N4 i3 ~
vCount pls_integer := 0;, a, i# ?1 q/ F3 d9 u7 P

* e& r, l" q( P# Jbegin
+ c+ v& Z6 U" B3 R: a; \
; \% f" B8 t" O4 s3 jif (not vMetaData.exists(vTable) or nvl(pForce, false))2 R" }6 t5 c5 m6 ^
 then0 n: J7 K1 y% k9 i9 w
 if not ObjectExists(pTable, cTable)
& r/ W! Q& ]) Y5 I% E  |3 o. G  C then
. J1 S, Z% u0 Z. T  raise_application_error(-20500,
9 z8 _. ~' l0 t) R      ’Unable to load metadata for ’ || nvl(pTable, ’NULL’) ||
0 O% g& [4 Q# U5 h      ’. ’ || ’Table does not exist.’$ R9 ^. {) w& l3 [1 N' s* ]& j
  );
3 G& X* G) z* }1 yend if; 7 |& ]* s& a4 |

8 [# V& v) R% n/ w  Jfor rec in (select table_name,# P4 a: c  p5 U/ U
logging,
# g3 Q( X2 P9 v/ Jltrim(rtrim(degree)) as degree,% i6 @8 O( l. ^+ T$ h
partitioned,
1 R/ h( y. x: a8 c2 Sbacked_up7 \* f) {5 s8 h/ v2 P
from user_tables
  E9 j8 R/ k8 I" ewhere table_name = vTable)8 h: T3 n( z& Y( ~5 Z/ y1 w
loop4 A9 s7 E0 y& p+ E# E* H  }1 W0 ^4 S2 E
* y% e3 ^& ]& |: U9 P$ m& D
 vFullMetaObject.aTable.aName := rec.table_name;
* O, S1 {8 \+ z) M vFullMetaObject.aTable.aType := rec.partitioned;! u& w2 a# e2 H! k) j$ y$ W
 vFullMetaObject.aTable.aLogging := rec.logging;
/ F6 B: Z& P& y; |$ G' p vFullMetaObject.aTable.aParallel := ltrim(rtrim(rec.degree));% ]/ g  t4 _, h6 i! l
 vFullMetaObject.aTable.aStatus := rec.backed_up;
/ s# Q" e: k/ S* d+ Y( ?vFullMetaObject.aTable.aDDLString := GetDDL(rec.table_name, cTable);6 x1 R( o" O( L- p
end loop;
, \$ G( c% P1 ]4 |: @# q7 D7 i& f  @9 V( [" F" p) H+ O8 s
for rec in (select index_name,9 F- _% F  H9 T* `
uniqueness,& s! |7 f) |0 g7 V" j7 C
logging,
9 Q& T4 f" \7 R, S1 A3 ?: rltrim(rtrim(degree)) as degree,7 n" w  C4 n, _9 i1 k
status
2 m4 V1 E3 x3 |1 i( }/ P9 l0 p1 V- bfrom user_indexes
$ e( t7 l  S1 n9 J5 ^# ]where table_name = vTable
7 I5 W( ]5 O* jand index_type != cLobType)
+ R* J% d+ |& {) ]3 M3 M" V- N0 Iloop, f3 `$ Y2 Q2 J$ J# e
, G* l. t; W+ n
vCount := vCount + 1;, j- `  \+ M+ R4 @2 \- Q% N
vFullMetaObject.aIndexes(vCount).aName := rec.index_name;
2 r. i0 @& S0 }9 P/ c" jvFullMetaObject.aIndexes(vCount).aType := rec.uniqueness;' u' u: ^, z) x# j6 Z/ |* d$ Q% o
vFullMetaObject.aIndexes(vCount).aLogging := rec.logging;
, \8 F0 U3 I7 ^$ v+ E( O, a+ avFullMetaObject.aIndexes(vCount).aParallel :=
& J2 P( |, k2 j4 k! h, {ltrim(rtrim(rec.degree));2 `2 o4 s  f5 L0 E
vFullMetaObject.aIndexes(vCount).aStatus := rec.status;$ h, h- ]( R1 ^5 h, F
vFullMetaObject.aIndexes(vCount).aDDLString :=7 p( C7 F3 U) v. Q' f
GetDDL(rec.index_name, cIndex);
5 v1 b1 O% g, X5 u. _0 I0 S5 g
  d' T: m6 @; l  U7 u; R; Oend loop;/ q% g( R, ?5 _5 j
0 k4 q( [& j$ G0 O( `1 `; P
vCount := 0;& m2 W4 u) z4 Q8 Z, j, I! G- g! A
for rec in (select constraint_name,constraint_type,status,search_condition,validated,rely from       user_constraints where table_name = vTable7 y$ M0 M# p( T1 a
order by decode(constraint_type,0 E6 c" Y, _% Y/ t( q
   cPKConsType, 10,5 l! V% ^) c) I7 B4 n
   cUNConsType, 20,% Q/ S3 i) @( G7 f5 w
   cFKConsType, 30,  Q: e, ]" R! v& R" t& X0 k( B
   cCKConsType, 40,
5 J+ a' Q3 _$ c% y# J   100),7 l6 j! s& E3 v+ X
constraint_name)
: [/ M8 I! `1 M0 P8 Q% Y; w1 }loop 9 I% E. x* t( ^
 vCount := vCount + 1;! H2 q' q5 `9 X* {
 vFullMetaObject.aConstraints(vCount).aName := rec.constraint_name;
4 N9 B1 X4 m% L* K+ U4 }5 s vFullMetaObject.aConstraints(vCount).aType := rec.constraint_type;
/ T, C" E* X, [4 K9 o6 Q+ J vFullMetaObject.aConstraints(vCount).aLogging := null;
# L2 }- q7 ~' f! w vFullMetaObject.aConstraints(vCount).aParallel := null;
& n) ]6 T& s8 @5 [ vFullMetaObject.aConstraints(vCount).aStatus := rec.status;
3 |9 i; ]1 z7 x- I, r vFullMetaObject.aConstraints(vCount).aValidated := rec.validated;, ]! ~8 C! n/ A& _
 vFullMetaObject.aConstraints(vCount).aRely := rec.rely;; g* q4 `! d7 q7 ^4 U
. V7 I3 S2 \  P, \
 if substr(rec.constraint_name, 1, length(cSYSPrefix)) = cSYSPrefix and
, x+ u: y4 f" C4 u; v      upper(rec.search_condition) like ’%IS ’ || cNotNull || ’%’
% V" j, U/ G' C3 N) f3 T9 z6 ? then
  M5 Q6 w( i" }1 M, G  vFullMetaObject.aConstraints(vCount).aDDLString := 0 `: ~! M0 r1 U. v2 R  _
     ’ALTER TABLE ’ || cDoubleQuote || vFullMetaObject.aTable.aName || cDoubleQuote || ’ ’ ||( f# ^8 R1 C* @9 V: U3 D9 S  G
     ’MODIFY ’ || replace(rec.search_condition, ’IS ’ || cNotNull, cNotNull) ||
) ]" \$ Q! k* D0 y     (case when vFullMetaObject.aConstraints(vCount).aValidated = cNotValidated/ ]9 f% |7 E7 y" B% d4 a
      then ’ ’ || cNovalidate
2 R5 o8 G! V& _1 Q+ L  I# D: K% s     else ’’end);
, I+ h7 j* n7 A+ f1 H' u. p else
; D* v6 M/ K/ R/ f5 z  vFullMetaObject.aConstraints(vCount).aDDLString := GetDDL(rec.constraint_name, cConstraint);
1 c1 P" o0 l. t5 o$ w  E. t end if;
! T* a( d& j: _. C" ?# `' @end loop;
% R9 G4 k0 |* n$ }! A8 \
' k$ h/ C# `% o+ P: YSetMeta(pTable, vFullMetaObject);   {0 m8 H# t4 t# O
end if;( ]0 ]) ~! n+ q* G5 ~! h
end Load;: p9 }+ G- y/ X- z- }
" j, ?: A) F5 N% H% K$ M6 U
procedure Reset
( q, ?6 a+ z. X  F(
# Q# u+ x* W$ d1 \* u* \ pTable in tString
1 j( w* _& q+ x* p. E5 w& c2 `)7 y) x* ]3 W/ \+ y7 k
is
" {: c; B9 l# h9 H$ ]0 ^- W1 Y! Zbegin7 R+ p  v* I5 `, K4 u
, _% F/ r+ z# P" ~& z3 U. L/ ]
vMetaData.delete(pTable);; r7 w5 W* J: D
7 X" n/ X" _* E$ x" c
end Reset;
+ C( c% W2 M4 j- W3 s$ l& q4 i2 z% ?9 \
/ I% A9 S; y, X. G, c" M/ }procedure Reset# L" ^! q; l6 t! C8 D
is& s: d  B1 y! H" d! t
begin* j% N0 Q" I! Y" `8 M( G1 d
 vMetaData.delete;4 e' Z1 x3 p& }* k/ ^. w
end Reset;
6 Y9 h# t6 S5 N8 x8 m! B! s0 I
) M1 K5 _) o$ \4 b- R; pfunction GetMeta
8 z# ?1 m. C$ `  v2 _1 S( _! H(( `% }; ~! v8 w' f/ w3 M
 pTable in tString,
0 a1 x. |. h& [ pForce in boolean := false
. e# h) u! e1 `7 n1 H8 W)0 v: H# ?$ a3 v$ T
return tFullMetaObject
! @6 {. F* W: j0 lis
; |* c$ y  z& N; N7 O. @begin1 t  }- ?- D) y' n

: P; W& u9 G( W3 z4 R2 \if (not vMetaData.exists(pTable) or nvl(pForce, false))
7 m$ c: f8 c" x0 H1 cthen
4 }: N& Z5 ]: W$ t Load(pTable, pForce);8 E9 p0 O. S8 }9 @* C

0 [  A8 j6 A  @# u5 e if not vMetaData.exists(pTable)
. V- {* t  Q" |: P$ U4 v then
4 n% H* i! k5 Q0 \  raise_application_error(-20501, ’Unable to find metadata for ’ || pTable || ’ in repository.’);
) z$ J( M. I$ y8 d, u2 a4 L end if;' K) _/ C( S. t. A9 @& k$ k
end if;
9 q" j; E5 M+ B  A1 m6 A$ ?/ Q. _# P& D
return vMetaData(pTable);
" t* [" C  u5 s9 E; ~6 v/ g4 r! Z
# q+ |. b4 i" ?; Oend GetMeta;1 m2 }+ P; A& Z9 H' x9 J

, Z9 o$ L; P) Nfunction GetMeta, A6 U) Q* Z/ @3 [/ e, v
 return tArrayFullMetaObjectByString* a6 n7 o8 q8 \! R- f) E  y
is
! ~8 W+ ?' o$ S! ]  X( sbegin
" q; z/ R" q) @2 w, T7 O8 d2 c6 p1 [0 x2 ]
return vMetaData;
3 b. J& F! x, {8 z2 C+ [- o) V
, w% L1 {- i, z, R# @6 Gend GetMeta;
3 n8 T) w5 f1 z& ^  |: B2 `
- I2 q' J# o3 f& ?/ Pprocedure SetMeta
$ s- u+ n1 w; N# ^(
0 ^* P0 ~2 P' q. A" M9 l0 k5 u5 h pTable in tString,5 D6 t. R5 t8 w3 S
 pFullMetaObject in tFullMetaObject+ j+ x. G/ u9 ]+ t) E
)
* }! ?3 Y3 Q. @is6 T8 y- K! R+ n# s: p
begin; M; q' l( I! g
3 I1 Y) J) w3 C6 ~; T) S
vMetaData(pTable) := pFullMetaObject;. u" b. H. c6 g# |
' r, H& L+ S9 [
end SetMeta;) J& C& {! i$ H1 m' R/ R8 [9 q( w, a

) ]- g) z% e& ^' p! a- c8 Mprocedure SetMeta$ w0 Z5 I' N. m7 `* Q* F: G
(0 X4 s: J$ X# c9 J3 J% f" [
 pArrayFullMetaObjectByString in tArrayFullMetaObjectByString
( v! y( a1 q+ z5 V5 W)
3 r, Y0 Z# ]( |- J/ m) Dis
) L& O: u1 A8 p* @* hbegin6 m5 W5 y7 `; Z6 i0 L

4 Y8 Z; d8 C  s0 T) b$ W0 n1 ^vMetaData := pArrayFullMetaObjectByString;3 j. W, y) K. n0 O+ m
7 ]" W3 d+ e% j' Y; R. S8 e
end SetMeta;1 _6 J. z6 w0 @1 f1 q/ k: l8 t

. L3 ~# d, b* _" ]procedure Show
6 d1 S7 ^  u5 j, J8 W(
3 y, {& p2 ?% l- v% R6 | pTable in tString
; v. ]% A& r) B" N% ~$ O% g)
8 M8 c' \3 i# C" `5 Ris
4 M( U+ b: E2 e, _! Y
9 B& \6 O1 J& ~9 U2 d1 m* o: RvFullMetaObject tFullMetaObject;; v' g7 ~3 X0 j2 J0 t& {

! X8 \- K1 n3 O9 Ubegin8 ]0 J" M8 j- ^
8 }1 l' \* R; W- N7 {* A" e% L
if (vMetaData.exists(pTable))8 [- E! Q4 {* _/ [+ t4 a9 W
then8 J) D& M* t; }0 B# U9 J
dbms_output.enable(1000000);* ~$ k& H% L& a4 G
0 c6 D& x$ c! B5 q* J& q, R/ I
vFullMetaObject := vMetaData(pTable);/ ^% Z: [& r" r: b* P; F
dbms_output.put_line(’Start Full Object: ’ || pTable);1 ^2 i8 ]- P" d# q; X
dbms_output.put_line(’Start Table: ’ || pTable);
, ~5 z& N1 l  _. T3 w3 }8 v2 JShow(vFullMetaObject.aTable);
" S+ \# v8 A$ [5 I7 Kdbms_output.put_line(’Finish Table: ’ || pTable);
: \* k- p, u* c) j- v5 c4 p* P
3 o# Z; h9 \0 h8 G- G2 idbms_output.put_line(’Start Indexes: ’ || pTable);1 M- {2 G' R/ S/ [5 u
if (vFullMetaObject.aIndexes.count > 0)
- v) M) j- `4 U" i: _$ y( W7 Ithen5 [- K! n; d1 C2 O7 t/ S8 M, Y
for nIndex in vFullMetaObject.aIndexes.first..vFullMetaObject.aIndexes.last; p. f% t, K% i8 _: P
loop
/ V4 a4 _4 I- l7 oShow(vFullMetaObject.aIndexes(nIndex));
+ F8 n1 s: |7 r9 _3 Gend loop;: |/ C& v8 t5 I
end if;
" y* n8 f- R; t0 x" idbms_output.put_line(’Finish Indexes: ’ || pTable);
" N9 d3 P6 K- a% F6 P+ d! {dbms_output.put_line(’Start Constraints: ’ || pTable);  ~' \0 x* @: H( \: S/ T$ h
if (vFullMetaObject.aConstraints.count > 0)
& G- p& X; M6 b5 M2 t4 [. Wthen  W$ W* }/ A( W  q. Q/ a
for nIndex in vFullMetaObject.aConstraints.first..vFullMetaObject.aConstraints.last: z' n- c7 D  i) |
loop
& h; G( r- ~3 D& P2 ^" R  uShow(vFullMetaObject.aConstraints(nIndex));! C" i! T0 v1 G2 ^/ i$ Y, U/ J; c
end loop;, M' ]7 d& s5 K# a
end if;: p! k$ Y9 q( g
dbms_output.put_line(’Finish Constraints: ’ || pTable);
6 a* d" h/ h$ f5 H8 Ldbms_output.put_line(’Start Triggers: ’ || pTable);
' B9 A. \3 _$ }# ?& kif (vFullMetaObject.aTriggers.count > 0)
8 R( c1 a9 P, P" D  U- U9 Athen- \. k" K1 K. ~- N: |9 R
for nIndex in vFullMetaObject.aTriggers.first..vFullMetaObject.aTriggers.last( A. }" [# X4 k1 D
loop
6 S' C8 d3 R$ x7 u- vShow(vFullMetaObject.aTriggers(nIndex));
5 R4 w( w% R. ^end loop;# \) c0 q: _0 y: i7 H
end if;9 J7 D, S+ W, W
dbms_output.put_line(’Finish Triggers: ’ || pTable); . [0 h; t% ]' `8 S  H4 n
dbms_output.put_line(’Finish Full Object: ’ || pTable);
% q; I1 i0 s  g5 Cend if;" Y2 B! F, m8 p- O7 Q
end Show; / U3 h/ C0 I" s( c1 b7 s
1 x- ~% i( u1 c% K+ j9 ~3 i
procedure Show
, D) l5 ~2 P) g. U3 dis
# s* f. Q2 w7 V( gvTable tString;
+ u$ G6 u8 e: \! j& Jbegin
( i" W6 ?* T( I! a# p1 t if vMetaData.count > 0
/ I6 k( B$ n* {% u/ u then
7 H1 q4 f8 f+ g$ C" S  dbms_output.put_line(’Total Meta Objects: ’ || to_char(vMetaData.count));
, `* Y. k. N1 y6 n9 s  vTable := vMetaData.first;
$ f! d, ~# u% T8 P9 b  while (vTable is not null)2 d7 ?2 k! |0 y' k
  loop
5 Q4 g. n. S8 m( N   Show(vTable);
& {0 D  m. o# P% I, b   vTable := vMetaData.next(vTable);
) n8 B) o! Z) e, M  end loop; ! p+ a! p0 N& u* V: l5 o# U3 C# _
 end if;# a: H0 y$ B% d+ e) m6 O
end Show;
. K* A& i. ^; C- d# N
2 P2 V7 h; e/ ?4 A& a7 A! ^% hbegin
+ B5 ~# ]( Y; dSetEnvironment; $ X; E$ ?/ g% v
end MetaDataPkg;
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-8-4 14:06:23 | 显示全部楼层

Oracle中提取和存储数据库对象的DDL

 下面的代码防止输出信息采用缩排或换行格式化:# r9 E% m8 B* N7 s$ e2 p
, P8 m( S9 o$ C& D; T
dbms_metadata.set_transform_param(dbms_metadata.session_transform, ’PRETTY’, false);
, Q* `/ i- [& W  下面的三行输出片段属性(物理属性、存储属性、表空间、日志等)、数据表的存储、表空间子句和索引对象定义:
1 w8 c0 S" m0 k. k+ B( k% X
4 ]* b$ _" V3 }" |0 Mdbms_metadata.set_transform_param(dbms_metadata.session_transform, ’SEGMENT_ATTRIBUTES’, true);
8 b! L; b; |1 J$ _' o  ydbms_metadata.set_transform_param(dbms_metadata.session_transform, ’STORAGE’, true);
. n) c3 m1 z5 B2 ]* odbms_metadata.set_transform_param(dbms_metadata.session_transform, ’TABLESPACE’, true);
% G$ x; S9 ^6 ]( R) b$ ]: _  明确地指定所有的物理、存储和日志属性是非常重要的--否则,它们会被设为默认值,而这个值可能与原始设置的值不同。% f& I# m! D6 e/ e$ S
2 `' `9 }, b& d6 e" F3 V+ Y
  SetEnvironment()过程最后的三行防止所有的非参考和参考约束被包含到表的DDL中。它还禁止独立的ALTER TABLE语句(如果必要,还可以禁止CREATE INDEX语句)来生成数据表约束:0 K7 N$ v% J0 y) c; u
/ @5 H" T; F& ^% j0 U
dbms_metadata.set_transform_param(dbms_metadata.session_transform, ’CONSTRAINTS’, false);
' f1 O, S: L% J. m) n1 ydbms_metadata.set_transform_param(dbms_metadata.session_transform, ’REF_CONSTRAINTS’, false);, X$ J# F$ v+ x
dbms_metadata.set_transform_param(dbms_metadata.session_transform, ’CONSTRAINTS_AS_ALTER’, false);9 {1 o9 O. p7 a! h
  为了达到最大的灵活性,最好分别提取数据表、索引和约束的对象定义并保证它们彼此都相互独立。通过这种办法,你可以控制这些对象的建立次序。. I, C+ ~5 A/ U* }

; q' o. P2 w  E  MetaDataPkg程序包的主要工作部分是MetaDataPkg.GetDDL()函数。MetaDataPkg.GetDDL()包含了列表1代码的扩展版本。添加到里面的是提取超过32767个字符的DDL字符串的能力。它可以帮助处理分区的数据表定义--随着分区数量的增长,它可能变得很长。这也是GetDDL()代码把DDL字符串分析并载入每个长达32767字符的字符串数组的原因。目前的代码版本只返回第一个数组元素,因此你需要修改这段代码,把该数组转换为tMetaObject记录类型的属性。这样就允许它处理长于32767字符的字符串,当然这种情况非常少见。; {: f' {, m7 c4 a+ f$ i( E
: f) i; D# i$ Z) B9 d4 K6 f8 t& o" C
  使用MetaDataPkg.GetMeta() API可以得到每个特定数据表的完整的元数据对象。这个API接受两个参数:pTable,它是表的名称;pForce,布尔型标记。当pForce被设置为TRUE的时候,它强迫元数据从Oracle数据字典中检索,接着把元数据载入存储器中--不管是否准备好了。但是默认的值是FALSE,因此第一个调用把元数据载入存储器中并返回tFullMetaObject类型的对象,后面的GetMeta()调用简单地从存储器中检索元数据。" B9 o/ f# V1 Q' k& C- f
0 C+ s1 E+ f1 X! X
  使用MetaDataPkg程序包
7 C# C. H+ Y6 O# i+ f, U) I/ S/ I0 M
  d! x! G) g# M5 o; E- N  为了演示如何使用MetaDataPkg程序包,我建立了一小段匿名代码块。它把EmpTest表中的元数据载入元数据存储器中,并输出它的内容。; s$ ^' c' B) N1 d. @

- c, ~# n0 S8 ?4 @: M  下面就是匿名的PL/SQL代码块:
# N- L5 i; l+ l, `: v; _$ g* O& H4 t5 H6 o+ L
declare
9 i; p6 |; j0 z! x3 u; ?6 ?  ivTable MetaDataPkg.tString := ’EmpTest’;
  Z; o# K4 O( l8 Z( _1 a$ p  d' rvRunStartTime number;
0 K+ R* g1 K. m& v" Lbegin
) @2 a; a* {5 R9 ZvRunStartTime := dbms_utility.get_time;
" E" P: y1 K) R: V9 b( f1 qMetaDataPkg.Load(vTable, true);0 T: u+ z3 ?6 T! F6 X* v4 o
MetaDataPkg.Show();- Y, E1 g1 `: z& b! K) F: `
dbms_output.put_line(’Time Elapsed: ’ ||
) y7 B) F1 N: k" o+ Gto_char((dbms_utility.get_time - vRunStartTime) / 100) || ’ sec.’);
8 y; T; w& G6 ^$ e* Y0 Cend;
8 G5 @9 ?) R2 j  V# ^  列表4显示了前面的代码的输出信息。
, s2 v5 x, g$ H6 [( x2 @" h  X' |: e- V2 ~" K3 E. u
  你可以看到,这段代码把EmpTest数据表和其索引、约束的全部元数据信息载入到存储器中,并在一秒钟之内把它检索出来了。你现在拥有了一个用于开发自动的解决方案的API了,它可以进行任何数据维护操作,包括更名、转换和删除数据库对象。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Woexam.Com ( 湘ICP备18023104号 )

GMT+8, 2024-9-23 02:11 , Processed in 0.670721 second(s), 30 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表