设为首页 | 加入收藏 RSS订阅 | 高级搜索 | 收藏本站 | 论坛
用户名: 密码: 验证码: gdcode 注册
首页 | 财税咨询 | 税收实务 | 纳税辅导 | 税收优惠 | 税务策划 | 财税实务 | 财务研究 | 税务知识 | 财软 | 学院 | 下载 | 数据库技术 | 论坛
logo

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

时间:2007-06-15 来源: 作者: 【字体: 减小 增大点击: 收藏 | 投稿
  
从对象(例如数据库表、索引、约束、触发器等)中提取DDL命令的普通方法涉及到的操作包括从这些对象中提取元数据(metadata),并把这些数据存储在内存中。尽管目前有很多脚本可以实现这样的功能,但是它们通常都是不完整的或者过时的。幸运的是,Oracle9.2提供了一个实现这样的功能的API:DBMS_METADATA程序包。

  在很多情况下,数据库中数据的维护操作要求我们提取多种对象(例如数据库表、索引、约束、触发器等)的DDL(DataDefinitionLanguage,数据定义语言)。

  最近我承担了一个任务,我需要编写一组数据库程序包来执行高性能的大量的数据删除(DELETE)操作。这样的操作要求我拥有提取和存储数据库对象DDL的相关技术。

  提取和存储数据库对象的DDL的方法如下:

  ·建立与源表结构相同的数据表,但是它不带主键、备用键和外部键约束。

财,软联盟,fs119.net



  ·例如,使用MyTable_X,其中MyTable是要被删除的目标数据表。

  ·把需要保存的数据插入新建立的数据表(MyTable_X)中。

  ·使用NOLOGGINGPARALLEL选项在新数据表上建立索引。

  ·在新数据表上建立约束。

  ·MyTable和MyTable_X数据表进行交换。把主表改名为MyTable_T,把MyTable_X改名为MyTable。

  ·验证结果并删除MyTable_T表。

  很明显,为了编写实现上面目标的代码,你必须提取数据库对象的元数据(定义和被选中的属性),并把它存储在内存中,这样在执行上面的操作的时候才能够使用它。

  在网上存在大量的脚本,它们可以从多种Oracle数据字典(user_tables、user_indexes、user_ind_columns、user_constraints、user_cons_columns等)中提取数据库对象的元数据,接着为特定的对象构造DDL命令。这些脚本的一个问题是,它们通常是SQL*Plus脚本,它会生成客户端文本文件,而这个文件不能被服务器端代码访问。它们的主要问题有:
财软联盟,fs119.net


  ·不完整:不能提取所有的选项,并组合进DDL语句中。

  ·过时了:这些脚本通常不支持Oracle最新的数据库特性--分区(partitioning)、基于函数的索引、自动段空间管理(ASSM)等。这些脚本可能崩溃或生成错误的DDL语句。

  问题总结:尽管有大量的从Oracle数据字典中提取数据库对象元数据的脚本,但是它们中的大多数要么不完整,要么过期了。

  解决方案:使用DBMS_METADATA程序包,学习如何用最佳的、没有错误的和易于维护的方式执行上面的事务。

  使用Oracle的本地API:DBMS_METADATA程序包

  Oracle数据库采用补充PL/SQL程序包的形式提供了丰富的预先包装好的API。Oracle9.2版本中引入的DBMS_METADATA程序包可能正好适合你的需求。它包含了用于检索数据库对象定义的API。

  我们将使用的API主要是DBMS_METADATA.GET_DDL函数。这个函数返回的对象定义SQL字符串是CLOB。它拥有下面一些输入参数:
财软联盟,fs119.net


  ·object_typeVARCHAR2

  ·nameVARCHAR2

  ·schemaVARCHAR2DEFAULTNULL

  ·versionVARCHAR2DEFAULT’COMPATIBLE’

  ·modelVARCHAR2DEFAULT’ORACLE’,

  ·transformVARCHAR2DEFAULT’DDL’

  下面建立了一个用于测试的EmpTest数据表,它带有索引和约束:

createtableEmpTest
(
empNointegernotnull,
lastNamevarchar2(30)notnull,
firstNamevarchar2(20)notnull,
jobvarchar2(9)’
hireDatedate’
isActivenumber(1)
constraintEmpTest_CK1
check(isActivein(0,1)),
salarynumber(9,2),
commisionnumber(9,2),
deptNonumber(2),
constraintEmpTest_PK
primarykey(empNo),
constraintEmpTest_AK1
unique(lastName,firstName)
);

createindexEmpTest_HireDate_Salary
onEmpTest
(
salary,
hireDate
);
  运行上面的脚本之后,就建立了一个带有三个索引(两个唯一的和一个不唯一的索引)的EmpTest表:

财,软联盟,fs119.net



selectindex_name,index_type,uniqueness
fromuser_indexes
wheretable_name=’EMPTEST’;
索引名称 索引类型 唯一性 EMPTEST_AK1 NORMAL UNIQUE EMPTEST_HIREDATE_SALARY NORMAL NONUNIQUE EMPTEST_PK NORMAL UNIQUE
  EmpTest表还包括六个约束:

  ·一个主键-EmpTest_PK

  ·一个备用键-EmpTest_AK

  ·一个检查约束-EmpTest_CK1

  ·系统生成的(SYS_*)三个非空的约束,名称如下:

约束名称 约束类型 索引名称 SYS_C002144065 C SYS_C002144066 C SYS_C002144067 C EMPTEST_CK1 C EMPTEST_PK P EMPTEST_PK EMPTEST_AK1 U EMPTEST_AK1 财.软联盟.fs119.net
  现在我们执行匿名的PL/SQL代码块来调用DBMS_METADATA.GET_DDL函数,检索数据表的定义。

  DBMS_OUTPUT程序包只能输出最长为255个字符的字符串,由于在处理数据表的DDL字符串的时候太容易超过这个限制,所以这是一个问题。为了解决这个问题,我们使用了本地过程Show()(列表1所示)。

  列表1:调用DBMS_METADATA.GET_DDL()函数的PL/SQL代码块

declare
vClobclob;
vLongStringvarchar2(32767);
vOffSetpls_integer:=0;
vLengthpls_integer:=0;
vTablevarchar2(30):=’EmpTest’;

procedureShow(pVariablevarchar2,pLineSizepls_integer:=80)
is
begin
dbms_output.enable(1000000);
if(length(pVariable)>pLineSize)
then
dbms_output.put_line(substr(pVariable,1,pLineSize));
Show(substr(pVariable,pLineSize1),pLineSize);
else
dbms_output.put_line(pVariable);
endif;

财管家,园,fs119.net


endShow;
begin
--获取DDL
vClob:=dbms_metadata.get_ddl(’TABLE’,upper(vTable));

--获取CLOB长度
vLength:=dbms_lob.GetLength(vClob);
dbms_output.put_line(’DDLlength:’||to_char(vLength));

vOffSet:=1;
dbms_lob.read(vClob,vLength,vOffSet,vLongString);
--关闭CLOB
if(dbms_lob.isOpen(vClob)>0)
then
dbms_lob.close(vClob);
endif;
Show(vLongString,80);
end;
  列表1生成下面的输出信息:

DDLlength:461
CREATETABLE"BORIS"."EMPTEST"
("EMPNO"NUMBER(*,0)NOTNULLENABLE,
"LASTNAME"VARCHAR2(30)NOTNULLENABLE,
"FIRSTNAME"VARCHAR2(20)NOTNULLENABLE,
"JOB"VARCHAR2(9),
"HIREDATE"DATE,
"ISACTIVE"NUMBER(1,0),
"SALARY"NUMBER(9,2),
"COMMISION"NUMBER(9,2),
"DEPTNO"NUMBER(2,0),
CONSTRAINT"EMPTEST_CK1"CHECK(isActivein(0,1))ENABLE,
CONSTRAINT"EMPTEST_PK"PRIMARYKEY("EMPNO")
USINGINDEXPCTFREE10INITRANS2MAXTRANS255
财管家.园.fs119.net

STORAGE(INITIAL65536NEXT1048576MINEXTENTS1MAXEXTENTS2147483645
PCTINCREASE0FREELISTS1FREELISTGROUPS1BUFFER_POOLDEFAULT)
TABLESPACE"TOOLS"ENABLE,CONSTRAINT"EMPTEST_AK1"UNIQUE("LASTNAME","FIRSTNAME")
USINGINDEXPCTFREE10INITRANS2MAXTRANS255
STORAGE(INITIAL65536NEXT1048576MINEXTENTS1MAXEXTENTS2147483645
PCTINCREASE0FREELISTS1FREELISTGROUPS1BUFFER_POOLDEFAULT)
TABLESPACE"TOOLS"ENABLE)PCTFREE10PCTUSED40INITRANS1
MAXTRANS255NOCOMPRESSLOGGING
STORAGE(INITIAL65536NEXT1048576MINEXTENTS1MAXEXTENTS2147483645
PCTINCREASE0FREELISTS1FREELISTGROUPS1BUFFER_POOLDEFAULT)
TABLESPACE"TOOLS"


  它运行的情况太好了,返回的数据表的DDL字符串带有主键EmpTest_PK、备用键EmpTest_AK1和检查约束EmpTest_CK1。它建立了两个唯一的索引来支持主键和备用键约束。这不是你需要的结果:你需要一个表,但是为了加快数据载入速度,它不要包含约束和索引。只有在数据载入工作完成以后,你才建立索引和约束。

财软,联盟,fs119.net


  保证对象的定义独立的另外一个原因在于灵活性:你可能需要改变对象建立的次序。

  现在可以设计一个数据结构来存储对象的元数据了。

财软联盟 fs119.net

财管家,园,fs119.net

财软联,盟,fs119.net


财管.家园.fs119.net

财管家.园.fs119.net

  元数据存储器:MetaDataPkg程序包规范

  首先,你必须建立记录类型来存储独立的对象(例如数据表、索引等)的所有必要信息:

subtypetStringisvarchar2(30);
subtypetDBStringisvarchar2(255);
subtypetDBLongStringisvarchar2(4000);
subtypetLongStringisvarchar2(32767);
typetArrayLongStringistableoftLongString
indexbypls_integer;
typetMetaObjectisrecord
(
aNametString,
aTypetString,
aLoggingtString,
aParalleltString,
aStatustString,
aValidatedtString,
aRelytString,
aDDLStringtLongString
);
  tMetaObject属性保存了下面一些信息:

  ·aName:对象的名称,例如EMPTEST_PK1。

  ·aType:对象的类型,例如’YES’(分区的)/’NO’(分区的)(用于表)、’UNIQUE’/’NONUNIQUE’(用于索引)、约束类型’P’/’U’/’C’/’R’(用于约束)。

财.管家园.fs119.net


  ·aLogging:对象的日志选项,例如’LOGGING’/’NOLOGGING’(用于表和索引)。

  ·aParallel:对象的平行程度(用于表和索引)。

  ·AStatus:对象的状态,例如’VALID’/’UNUSABLE’用于索引、’Y’(备份了)/’N’(未备份)用于表。

  ·AValidated:对象的验证选项,例如’VALIDATED’/’NOTVALIDATED’(用于约束)。

  ·ARely:对象的依赖选项,例如’RELY’/’NORELY’(用于约束)。

  ·ADDLString:对象的定义SQL字符串。

  现在你必须定义一个相关的数组类型,它能够列举出某种类型的对象,从保存tMetaObject类型的多个对象,例如,所有的EmpTest索引:

typetArrayMetaObjectistableoftMetaObject
indexbypls_integer;
  下一步需要建立一个记录类型,它包含了数据表表自身(aTable)的tMetaObject属性和三个tArrayMetaObject属性:一个用于索引(aIndexes),一个用于约束(aConstraints),一个用于触发器(aTriggers): 财管家 园 fs119.net

typetFullMetaObjectisrecord
(
aTabletMetaObject,
aIndexestArrayMetaObject,
aConstraintstArrayMetaObject,
aTriggerstArrayMetaObject
);
  tFullMetaObject对象类型保存了单个表的全部对象的元数据。最后,位于顶层的类型是tFullMetaObject数组。TarrayFullMetaObjectByString类型是tFullMetaObject的一个表,索引类型是varchar2(30)。

  列表2:MetaDataPkg程序包规范

  用如下的方式建立或更新MetaDataPkg:

cEnabledconstantchar(7):=’ENABLED’;
cDisabledconstantchar(8):=’DISABLED’;
cUsableconstantchar(6):=’USABLE’;
cUnusableconstantchar(8):=’UNUSABLE’;
cValidconstantchar(5):=’VALID’;
cInvalidconstantchar(7):=’INVALID’;

cTableconstantchar(5):=’TABLE’; 财软联盟.fs119.net
cViewconstantchar(4):=’VIEW’;
cIndexconstantchar(5):=’INDEX’;
cConstraintconstantchar(10):=’CONSTRAINT’;
cTriggerconstantchar(7):=’TRIGGER’;
cLobTypeconstantchar(3):=’LOB’;
cClobTypeconstantchar(4):=’CLOB’;
cBlobTypeconstantchar(4):=’BLOB’;
cPackageconstantchar(7):=’PACKAGE’;
cPackageBodyconstantchar(12):=’PACKAGEBODY’;
cProcedureconstantchar(9):=’PROCEDURE’;
cFunctionconstantchar(8):=’FUNCTION’;
cSequenceconstantchar(8):=’SEQUENCE’;
cSynonymconstantchar(7):=’SYNONYM’;
cTypeconstantchar(4):=’TYPE’;
cColumnconstantchar(6):=’COLUMN’;
cJavaSourceconstantchar(11):=’JAVASOURCE’;
cJavaClassconstantchar(10):=’JAVACLASS’;

cYesconstantchar(3):=’YES’;
cNoconstantchar(2):=’NO’;

cPKConsTypeconstantchar(1):=’P’;
cUNConsTypeconstantchar(1):=’U’;
cFKConsTypeconstantchar(1):=’R’;
cCKConsTypeconstantchar(1):=’C’;

cDropStorageconstantchar(12):=’DROPSTORAGE’; 财管家园.fs119.net
cReuseStorageconstantchar(13):=’REUSESTORAGE’;
cCascadeconstantchar(19):=’CASCADECONSTRAINTS’;
cNoCascadeconstantchar(10):=’NOCASCADE’;
cEnableconstantchar(6):=’ENABLE’;
cNovalidateconstantchar(10):=’NOVALIDATE’;
cRelyconstantchar(4):=’RELY’;
cNoRelyconstantchar(6):=’NORELY’;
cValidatedconstantchar(9):=’VALIDATED’;
cNotValidatedconstantchar(13):=’NOTVALIDATED’;
cLoggingconstantchar(7):=’LOGGING’;
cNoLoggingconstantchar(9):=’NOLOGGING’;
cParallelconstantchar(8):=’PARALLEL’;
cNoParallelconstantchar(10):=’NOPARALLEL’;
cNullconstantchar(4):=’NULL’;
cNotNullconstantchar(8):=’NOTNULL’;
cDefaultconstantchar(7):=’DEFAULT’;

cSYSPrefixconstantchar(4):=’SYS_’;
cDoubleQuoteconstantchar(1):=’"’;

subtypetStringisvarchar2(30);
subtypetDBStringisvarchar2(255);
subtypetDBLongStringisvarchar2(4000);
subtypetLongStringisvarchar2(32767);

typetArrayLongStringistableoftLongString
indexbypls_integer; 财软联 盟 fs119.net

typetMetaObjectisrecord
(
 aNametString,
 aTypetString,
 aLoggingtString,
 aParalleltString,
 aStatustString,
 aValidatedtString,
 aRelytString,
 aDDLStringtLongString
);

typetArrayMetaObjectistableoftMetaObject
indexbypls_integer;

typetFullMetaObjectisrecord
(
 aTabletMetaObject,
 aIndexestArrayMetaObject,
 aConstraintstArrayMetaObject,
 aTriggerstArrayMetaObject
);

typetArrayFullMetaObjectByStringistableoftFullMetaObject
indexbyvarchar2(30);

procedureLoad
(
 pTableintString,
 pForceinboolean:=false
);

procedureReset
(
 pTableintString
);

procedureReset;

functionGetMeta
(
 pTableintString,
 pForceinboolean:=false
)
returntFullMetaObject;

functionGetMeta
returntArrayFullMetaObjectByString;

procedureSetMeta
(
 pTableintString,
 pFullMetaObjectintFullMetaObject
);

procedureSetMeta
(
 pArrayFullMetaObjectByStringintArrayFullMetaObjectByString 财管家.园.fs119.net
);

procedureShow
(
 pTableintString
);

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

  ·MetaDataPkg.Load()过程:把特定表的元数据信息载入存储器中。

  ·MetaDataPkg.GetMeta()函数:它从存储器中检索tFullMetaObject类型的对象。

  ·MetaDataPkg.SetMeta()过程(重载的):把对象的元数据存储到存储器中。

  ·MetaDataPkg.Reset过程(重载的):对存储器复位。

  ·MetaDataPkg.Show过程(重载的):显示存储器的内容。
财软联.盟.fs119.net

财,软联盟,fs119.net

财,管家园,fs119.net


财管 家园 fs119.net

财,软联盟,fs119.net

  实现所有这些事务的代码

  列表3显示了MetaDataPkg程序包主体代码的一些解释。私有过程SetEnvironment()包含了所有的环境设置代码。在程序包的初始化部分会调用这个过程,因此在每个对话中它都只执行一次,符合你的需求(你希望在开头设置一次)。程序包提供了用于设置环境参数的API:DBMS_METADATA.SET_TRANSFORM_PARAM()过程。

  列表3:MetaDataPkg程序包主体

vMetaDatatArrayFullMetaObjectByString;

procedureSetEnvironment
is
begin
 dbms_metadata.set_transform_param(
  dbms_metadata.session_transform,’PRETTY’,false);
 dbms_metadata.SET_TRANSFORM_PARAM(
  dbms_metadata.session_transform,’SEGMENT_ATTRIBUTES’,true);
 dbms_metadata.set_transform_param(
  dbms_metadata.session_transform,’STORAGE’,true);
 dbms_metadata.set_transform_param( 财管家园.fs119.net
  dbms_metadata.session_transform,’TABLESPACE’,true);
 dbms_metadata.set_transform_param(
  dbms_metadata.session_transform,’CONSTRAINTS’,false);
 dbms_metadata.set_transform_param(
  dbms_metadata.session_transform,’REF_CONSTRAINTS’,false);
 dbms_metadata.set_transform_param(
  dbms_metadata.session_transform,’CONSTRAINTS_AS_ALTER’,false);

endSetEnvironment;

procedurePrint
(
 pStringvarchar2,
 pLineSizepositive:=80
)
is

vLineSizepls_integer:=least(nvl(pLineSize,80),255);

begin
 dbms_output.enable(1000000);

 if(length(pString)>vLineSize)
 then
  dbms_output.put_line(substr(pString,1,vLineSize));
  Print(substr(pString,pLineSize1),vLineSize);
 else
  dbms_output.put_line(pString);
 endif;

endPrint;

procedureShow
(
 pMetaObjectintMetaObject
)
is
begin
dbms_output.put_line(’***’);
dbms_output.put_line(’Name:’||pMetaObject.aName);

财软联盟.fs119.net


dbms_output.put_line(’Type:’||pMetaObject.aType);
dbms_output.put_line(’Logging:’||pMetaObject.aLogging);
dbms_output.put_line(’Parallel:’||
to_char(pMetaObject.aParallel));
dbms_output.put_line(’Status:’||pMetaObject.aStatus);
dbms_output.put_line(’Validated:’||
pMetaObject.aValidated);
dbms_output.put_line(’Rely:’||pMetaObject.aRely);
print(’DDLString:’||pMetaObject.aDDLString,255);
dbms_output.put_line(’***’);
endShow;

functionGetDDL
(
 pNameintString,
 pTypeintString
)
returntLongString
is
vClobclob;

vLongStringstArrayLongString;

vFullLengthpls_integer:=0;
vOffSetpls_integer:=0;
vLengthpls_integer:=0;

begin

vClob:=dbms_metadata.get_ddl(pType,upper(pName));

vFullLength:=dbms_lob.GetLength(vClob);

fornIndexin1..ceil(vFullLength/32767)
loop
 vOffSet:=vLength1;
 vLength:=least(vFullLength-(nIndex-1)*32767,32767);

 dbms_lob.read(vClob,vLength,vOffSet,vLongStrings(nIndex));
财,软联盟,fs119.net


 vLongStrings(nIndex):=replace(vLongStrings(nIndex),
    cDoubleQuote||user||cDoubleQuote||’.’,
    ’’);

 vLongStrings(nIndex):=ltrim(rtrim(replace(vLongStrings(nIndex),chr(10),’’)));
endloop;

if(dbms_lob.isOpen(vClob)>0)
then
 dbms_lob.close(vClob);
endif;

returnvLongStrings(1);

endGetDDL;

functionObjectExists
(
 pObjectNameintString,
 pObjectTypeintString,
 pTableNameintString:=null
)
returnboolean
is

vCountpls_integer:=0;
vObjectNametString:=ltrim(rtrim(pObjectName));
vObjectTypetString:=upper(ltrim(rtrim(pObjectType)));
vTableNametString:=upper(ltrim(rtrim(pTableName)));

begin

case
 whenvObjectType=cColumn
 then
 selectcount(*)
  intovCount
  fromDual
  whereexists(select’1’
  fromuser_tab_columns
  wherecolumn_name=upper(vObjectName)
  andtable_name=vTableName);

 whenvObjectType=cConstraint
财管家园,fs119.net

 then
  selectcount(*)
  intovCount
  fromDual
  whereexists(select’1’
  fromuser_constraints
  whereconstraint_name=upper(vObjectName)
  andtable_name=vTableName);

whenvObjectTypein(cJavaSource,cJavaClass)
then
 selectcount(*)
 intovCount
 fromDual
 whereexists(select’1’
 fromuser_objects
 whereobject_name=vObjectNameandobject_type=vObjectType);

 else
  selectcount(*)
  intovCount
  fromDual
  whereexists(select’1’
  fromuser_objects
  whereobject_name=upper(pObjectName)
  andobject_type=vObjectType);
 endcase;

return(vCount>0);

endObjectExists;

procedureLoad
(
 pTableintString,
 pForceinboolean:=false
)
is

vFullMetaObjecttFullMetaObject;

vTabletString:=upper(ltrim(rtrim(pTable)));
vCountpls_integer:=0;

begin

if(notvMetaData.exists(vTable)ornvl(pForce,false))
 then 财软联盟,fs119.net
 ifnotObjectExists(pTable,cTable)
 then
  raise_application_error(-20500,
      ’Unabletoloadmetadatafor’||nvl(pTable,’NULL’)||
      ’.’||’Tabledoesnotexist.’
  );
endif;

forrecin(selecttable_name,
logging,
ltrim(rtrim(degree))asdegree,
partitioned,
backed_up
fromuser_tables
wheretable_name=vTable)
loop

 vFullMetaObject.aTable.aName:=rec.table_name;
 vFullMetaObject.aTable.aType:=rec.partitioned;
 vFullMetaObject.aTable.aLogging:=rec.logging;
 vFullMetaObject.aTable.aParallel:=ltrim(rtrim(rec.degree));
 vFullMetaObject.aTable.aStatus:=rec.backed_up;
vFullMetaObject.aTable.aDDLString:=GetDDL(rec.table_name,cTable);
endloop;

forrecin(selectindex_name,
uniqueness,
logging,
ltrim(rtrim(degree))asdegree,
status
fromuser_indexes
wheretable_name=vTable
andindex_type!=cLobType)
loop

vCount:=vCount1;
vFullMetaObject.aIndexes(vCount).aName:=rec.index_name; 财管.家园.fs119.net
vFullMetaObject.aIndexes(vCount).aType:=rec.uniqueness;
vFullMetaObject.aIndexes(vCount).aLogging:=rec.logging;
vFullMetaObject.aIndexes(vCount).aParallel:=
ltrim(rtrim(rec.degree));
vFullMetaObject.aIndexes(vCount).aStatus:=rec.status;
vFullMetaObject.aIndexes(vCount).aDDLString:=
GetDDL(rec.index_name,cIndex);

endloop;

vCount:=0;
forrecin(selectconstraint_name,constraint_type,status,search_condition,validated,relyfrom      user_constraintswheretable_name=vTable
orderbydecode(constraint_type,
   cPKConsType,10,
   cUNConsType,20,
   cFKConsType,30,
   cCKConsType,40,
   100),
constraint_name)
loop
 vCount:=vCount1;
 vFullMetaObject.aConstraints(vCount).aName:=rec.constraint_name;
 vFullMetaObject.aConstraints(vCount).aType:=rec.constraint_type;
 vFullMetaObject.aConstraints(vCount).aLogging:=null;
 vFullMetaObject.aConstraints(vCount).aParallel:=null;
 vFullMetaObject.aConstraints(vCount).aStatus:=rec.status; 财管家 园 fs119.net
 vFullMetaObject.aConstraints(vCount).aValidated:=rec.validated;
 vFullMetaObject.aConstraints(vCount).aRely:=rec.rely;

 ifsubstr(rec.constraint_name,1,length(cSYSPrefix))=cSYSPrefixand
      upper(rec.search_condition)like’%IS’||cNotNull||’%’
 then
  vFullMetaObject.aConstraints(vCount).aDDLString:=
     ’ALTERTABLE’||cDoubleQuote||vFullMetaObject.aTable.aName||cDoubleQuote||’’||
     ’MODIFY’||replace(rec.search_condition,’IS’||cNotNull,cNotNull)||
     (casewhenvFullMetaObject.aConstraints(vCount).aValidated=cNotValidated
      then’’||cNovalidate
     else’’end);
 else
  vFullMetaObject.aConstraints(vCount).aDDLString:=GetDDL(rec.constraint_name,cConstraint);
 endif;
endloop;

SetMeta(pTable,vFullMetaObject);
endif;
endLoad;

procedureReset
(
 pTableintString
)
is
begin

vMetaData.delete(pTable);

endReset;
财.软联盟.fs119.net


procedureReset
is
begin
 vMetaData.delete;
endReset;

functionGetMeta
(
 pTableintString,
 pForceinboolean:=false
)
returntFullMetaObject
is
begin

if(notvMetaData.exists(pTable)ornvl(pForce,false))
then
 Load(pTable,pForce);

 ifnotvMetaData.exists(pTable)
 then
  raise_application_error(-20501,’Unabletofindmetadatafor’||pTable||’inrepository.’);
 endif;
endif;

returnvMetaData(pTable);

endGetMeta;

functionGetMeta
 returntArrayFullMetaObjectByString
is
begin

returnvMetaData;

endGetMeta;

procedureSetMeta
(
 pTableintString,
 pFullMetaObjectintFullMetaObject
)
is
begin

vMetaData(pTable):=pFullMetaObject;

endSetMeta;

procedureSetMeta
(
 pArrayFullMetaObjectByStringintArrayFullMetaObjectByString
)
is
begin

vMetaData:=pArrayFullMetaObjectByString;

endSetMeta;

procedureShow
(
 pTableintString 财软联,盟,fs119.net
)
is

vFullMetaObjecttFullMetaObject;

begin

if(vMetaData.exists(pTable))
then
dbms_output.enable(1000000);

vFullMetaObject:=vMetaData(pTable);
dbms_output.put_line(’StartFullObject:’||pTable);
dbms_output.put_line(’StartTable:’||pTable);
Show(vFullMetaObject.aTable);
dbms_output.put_line(’FinishTable:’||pTable);

dbms_output.put_line(’StartIndexes:’||pTable);
if(vFullMetaObject.aIndexes.count>0)
then
fornIndexinvFullMetaObject.aIndexes.first..vFullMetaObject.aIndexes.last
loop
Show(vFullMetaObject.aIndexes(nIndex));
endloop;
endif;
dbms_output.put_line(’FinishIndexes:’||pTable);
dbms_output.put_line(’StartConstraints:’||pTable);
if(vFullMetaObject.aConstraints.count>0)
then
fornIndexinvFullMetaObject.aConstraints.first..vFullMetaObject.aConstraints.last
loop
Show(vFullMetaObject.aConstraints(nIndex));
endloop;
endif;
dbms_output.put_line(’FinishConstraints:’||pTable);
dbms_output.put_line(’StartTriggers:’||pTable); 财.管家园.fs119.net
if(vFullMetaObject.aTriggers.count>0)
then
fornIndexinvFullMetaObject.aTriggers.first..vFullMetaObject.aTriggers.last
loop
Show(vFullMetaObject.aTriggers(nIndex));
endloop;
endif;
dbms_output.put_line(’FinishTriggers:’||pTable);
dbms_output.put_line(’FinishFullObject:’||pTable);
endif;
endShow;

procedureShow
is
vTabletString;
begin
 ifvMetaData.count>0
 then
  dbms_output.put_line(’TotalMetaObjects:’||to_char(vMetaData.count));
  vTable:=vMetaData.first;
  while(vTableisnotnull)
  loop
   Show(vTable);
   vTable:=vMetaData.next(vTable);
  endloop;
 endif;
endShow;

begin
SetEnvironment;
endMetaDataPkg;
  下面的代码防止输出信息采用缩排或换行格式化:

dbms_metadata.set_transform_param(dbms_metadata.session_transform,’PRETTY’,false); 财管家园 fs119.net
  下面的三行输出片段属性(物理属性、存储属性、表空间、日志等)、数据表的存储、表空间子句和索引对象定义:

dbms_metadata.set_transform_param(dbms_metadata.session_transform,’SEGMENT_ATTRIBUTES’,true);
dbms_metadata.set_transform_param(dbms_metadata.session_transform,’STORAGE’,true);
dbms_metadata.set_transform_param(dbms_metadata.session_transform,’TABLESPACE’,true);
  明确地指定所有的物理、存储和日志属性是非常重要的--否则,它们会被设为默认值,而这个值可能与原始设置的值不同。

  SetEnvironment()过程最后的三行防止所有的非参考和参考约束被包含到表的DDL中。它还禁止独立的ALTERTABLE语句(如果必要,还可以禁止CREATEINDEX语句)来生成数据表约束:

dbms_metadata.set_transform_param(dbms_metadata.session_transform,’CONSTRAINTS’,false);
财软.联盟.fs119.net

dbms_metadata.set_transform_param(dbms_metadata.session_transform,’REF_CONSTRAINTS’,false);
dbms_metadata.set_transform_param(dbms_metadata.session_transform,’CONSTRAINTS_AS_ALTER’,false);
  为了达到最大的灵活性,最好分别提取数据表、索引和约束的对象定义并保证它们彼此都相互独立。通过这种办法,你可以控制这些对象的建立次序。

  MetaDataPkg程序包的主要工作部分是MetaDataPkg.GetDDL()函数。MetaDataPkg.GetDDL()包含了列表1代码的扩展版本。添加到里面的是提取超过32767个字符的DDL字符串的能力。它可以帮助处理分区的数据表定义--随着分区数量的增长,它可能变得很长。这也是GetDDL()代码把DDL字符串分析并载入每个长达32767字符的字符串数组的原因。目前的代码版本只返回第一个数组元素,因此你需要修改这段代码,把该数组转换为tMetaObject记录类型的属性。这样就允许它处理长于32767字符的字符串,当然这种情况非常少见。

财 软联盟 fs119.net



  使用MetaDataPkg.GetMeta()API可以得到每个特定数据表的完整的元数据对象。这个API接受两个参数:pTable,它是表的名称;pForce,布尔型标记。当pForce被设置为TRUE的时候,它强迫元数据从Oracle数据字典中检索,接着把元数据载入存储器中--不管是否准备好了。但是默认的值是FALSE,因此第一个调用把元数据载入存储器中并返回tFullMetaObject类型的对象,后面的GetMeta()调用简单地从存储器中检索元数据。

  使用MetaDataPkg程序包

  为了演示如何使用MetaDataPkg程序包,我建立了一小段匿名代码块。它把EmpTest表中的元数据载入元数据存储器中,并输出它的内容。

  下面就是匿名的PL/SQL代码块:

declare
vTableMetaDataPkg.tString:=’EmpTest’;
vRunStartTimenumber;
begin
vRunStartTime:=dbms_utility.get_time; 财软.联盟.fs119.net
MetaDataPkg.Load(vTable,true);
MetaDataPkg.Show();
dbms_output.put_line(’TimeElapsed:’||
to_char((dbms_utility.get_time-vRunStartTime)/100)||’sec.’);
end;
  列表4显示了前面的代码的输出信息。

  你可以看到,这段代码把EmpTest数据表和其索引、约束的全部元数据信息载入到存储器中,并在一秒钟之内把它检索出来了。你现在拥有了一个用于开发自动的解决方案的API了,它可以进行任何数据维护操作,包括更名、转换和删除数据库对象。 财管,家园,fs119.net

财软联.盟.fs119.net

财软联盟 fs119.net


文章摘自网络,如有侵权,请与我们联系.
数据统计中!!
上一篇:Oracle9i数据库异常关闭后的启动
下一篇:PL/SQL实现Oracle数据库任务调度

用户名: 密码: 匿名? 注册