oracledmlddl:Oracle中提取和存储数据库对象的DDL来源: 发布时间:星期三, 2008年12月31日 浏览:2次 评论:0
="t18">
从对象(例如数据库表、索引、约束、触发器等)中提取DDL命令普通思路方法涉及到操作包括从这些对象中提取元数据(metadata)并把这些数据存储在内存中尽管目前有很多脚本可以实现这样功能但是它们通常都是不完整或者过时
幸运是Oracle 9.2提供了个实现这样功能API:DBMS_METADATA包
在很多情况下数据库中数据维护操作要求我们提取多种对象(例如数据库表、索引、约束、触发器等)DDL(Data Definition Language数据定义语言) 最近我承担了个任务我需要编写组数据库包来执行高性能大量数据删除(DELETE)操作这样操作要求我拥有提取和存储数据库对象DDL相关技术 提取和存储数据库对象DDL思路方法如下: · 建立和源表结构相同数据表但是它不带主键、备用键和外部键约束 · 例如使用MyTable_X其中MyTable是要被删除目标数据表 · 把需要保存数据插入新建立数据表(MyTable_X)中 · 使用NOLOGGING PARALLEL选项在新数据表上建立索引 · 在新数据表上建立约束 · MyTable和MyTable_X数据表进行交换把主表改名为MyTable_T把MyTable_X改名为MyTable · 验证结果并删除MyTable_T表 很明显为了编写实现上面目标代码你必须提取数据库对象元数据(定义和被选中属性)并把它存储在内存中这样在执行上面操作时候才能够使用它 在网上存在大量脚本它们可以从多种Oracle数据字典(user_tables、user_indexes、user_ind_columns、user_constras、user_cons_columns等)中提取数据库对象元数据接着为特定对象构造DDL命令这些脚本个问题是它们通常是SQL*Plus脚本它会生成客户端文本文件而这个文件不能被服务器端代码访问它们主要问题有: · 不完整:不能提取所有选项并组合进DDL语句中 · 过时了:这些脚本通常不支持Oracle最新数据库特性--分区(partitioning)、基于索引、自动段空间治理(ASSM)等这些脚本可能崩溃或生成DDL语句 问题整理总结:尽管有大量从Oracle数据字典中提取数据库对象元数据脚本但是它们中大多数要么不完整要么过期了 解决方案:使用DBMS_METADATA包学习如何用最佳、没有和易于维护方式执行上面事务 使用Oracle本地API:DBMS_METADATA包 Oracle数据库采用补充PL/SQL包形式提供了丰富预先包装好APIOracle 9.2版本中引入DBMS_METADATA包可能正好适合你需求它包含了用于检索数据库对象定义API 我们将使用API主要是DBMS_METADATA.GET_DDL这个返回对象定义SQL串是CLOB它拥有下面些输入参数: · object_type VARCHAR2 · name VARCHAR2 · schema VARCHAR2 DEFAULT NULL · version VARCHAR2 DEFAULT ’COMPATIBLE’ · model VARCHAR2 DEFAULT ’ORACLE’, · transform VARCHAR2 DEFAULT ’DDL’ 下面建立了个用于测试EmpTest数据表它带有索引和约束: create table EmpTest ( empNo eger not null, lastName varchar2(30) not null, firstName varchar2(20) not null, job varchar2(9) ’ hireDate date ’ isActive number(1) constra EmpTest_CK1 check (isActive in (0,1)) , salary number(9,2) , commision number(9,2) , deptNo number(2) , constra EmpTest_PK primary key (empNo), constra EmpTest_AK1 unique (lastName, firstName) ); create index EmpTest_HireDate_Salary on EmpTest ( salary, hireDate ); 运行上面脚本的后就建立了个带有 3个索引(两个唯和个不唯索引)EmpTest表: select index_name, index_type, uniqueness from user_indexes where table_name = ’EMPTEST’; 索引名称 索引类型 唯性 EMPTEST_AK1 NORMAL UNIQUE EMPTEST_HIREDATE_SALARY NORMAL NONUNIQUE EMPTEST_PK NORMAL UNIQUE EmpTest表还包括 6个约束: · 个主键-EmpTest_PK · 个备用键-EmpTest_AK · 个检查约束-EmpTest_CK1 · 系统生成(SYS_*) 3个非空约束名称如下: 约束名称 约束类型 索引名称 SYS_C002144065 C SYS_C002144066 C SYS_C002144067 C EMPTEST_CK1 C EMPTEST_PK P EMPTEST_PK EMPTEST_AK1 U EMPTEST_AK1 现在我们执行匿名PL/SQL代码块来DBMS_METADATA.GET_DDL检索数据表定义 DBMS_OUTPUT包只能输出最长为255个串由于在处理数据表DDL串时候太轻易超过这个限制所以这是个问题为了解决这个问题我们使用了本地过程Show(列表1所示) 列表1:DBMS_METADATA.GET_DDLPL/SQL代码块 declare vClob clob; vLongString varchar2(32767); vOffSet pls_eger := 0; vLength pls_eger := 0; vTable varchar2(30) := ’EmpTest’; procedure Show (pVariable varchar2, pLineSize pls_eger := 80) is begin dbms_output.enable(1000000); (length(pVariable) > pLineSize) then dbms_output.put_line(substr(pVariable, 1, pLineSize)); Show(substr(pVariable, pLineSize + 1), pLineSize); dbms_output.put_line(pVariable); end ; end Show; begin -- 获取 DDL vClob := dbms_metadata.get_ddl(’TABLE’, upper(vTable)); -- 获取 CLOB 长度 vLength := dbms_lob.GetLength(vClob); dbms_output.put_line(’DDL length: ’ to_char(vLength)); vOffSet := 1; dbms_lob.read(vClob, vLength, vOffSet, vLongString); -- 关闭 CLOB (dbms_lob.isOpen(vClob) > 0) then dbms_lob.close(vClob); end ; Show(vLongString, 80); end; 列表1生成下面输出信息: DDL length: 461 CREATE TABLE "BORIS"."EMPTEST" ( "EMPNO" NUMBER(*,0) NOT NULL ENABLE, "LASTNAME" VARCHAR2(30) NOT NULL ENABLE, "FIRSTNAME" VARCHAR2(20) NOT NULL ENABLE, "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 (isActive in (0,1)) ENABLE, CONSTRAINT "EMPTEST_PK" PRIMARY KEY ("EMPNO") USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT) TABLESPACE "TOOLS" ENABLE, CONSTRAINT "EMPTEST_AK1" UNIQUE ("LASTNAME", "FIRSTNAME") USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT) TABLESPACE "TOOLS" ENABLE) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT) TABLESPACE "TOOLS" 它运行情况太好了返回数据表DDL串带有主键EmpTest_PK、备用键EmpTest_AK1和检查约束EmpTest_CK1它建立了两个唯索引来支持主键和备用键约束这不是你需要结果:你需要个表但是为了加快数据载入速度它不要包含约束和索引只有在数据载入工作完成以后你才建立索引和约束 保证对象定义独立另外个原因在于灵活性:你可能需要改变对象建立次序 现在可以设计个数据结构来存储对象元数据了 元数据存储器:MetaDataPkg包规范标准 首先你必须建立记录类型来存储独立对象(例如数据表、索引等)所有必要信息: suBType tString is varchar2(30); subtype tDBString is varchar2(255); subtype tDBLongString is varchar2(4000); subtype tLongString is varchar2(32767); type tArrayLongString is table of tLongString index by pls_eger; type tMetaObject is record ( aName tString, aType tString, aLogging tString, aParallel tString, aStatus tString, aValidated tString, aRely tString, aDDLString tLongString ); tMetaObject属性保存了下面些信息: · aName:对象名称例如EMPTEST_PK1 · aType:对象类型例如’YES’ (分区)/’NO’ (分区) (用于表)、 ’UNIQUE’/’NONUNIQUE’ (用于索引)、 约束类型 ’P’/’U’/’C’/’R’ (用于约束) · aLogging:对象日志选项例如’LOGGING’/ ’NOLOGGING’ (用于表和索引) · aParallel: 对象平行程度(用于表和索引) · AStatus:对象状态例如’VALID’/’UNUSABLE’ 用于索引、 ’Y’ (备份了)/’N’ (未备份)用于表 · AValidated:对象验证选项例如’VALIDATED’/’NOT VALIDATED’(用于约束) · ARely:对象依靠选项例如’RELY’/’NORELY’ (用于约束) · ADDLString:对象定义SQL串 现在你必须定义个相关类型它能够列举出某种类型对象从保存tMetaObject类型多个对象例如所有EmpTest索引: type tArrayMetaObject is table of tMetaObject index by pls_eger; 下步需要建立个记录类型它包含了数据表表自身(aTable)tMetaObject属性和 3个tArrayMetaObject属性:个用于索引(aIndexes)个用于约束(aConstras)个用于触发器(aTriggers): type tFullMetaObject is record ( aTable tMetaObject, aIndexes tArrayMetaObject, aConstras tArrayMetaObject, aTriggers tArrayMetaObject ); tFullMetaObject对象类型保存了单个表全部对象元数据最后位于顶层类型是tFullMetaObjectT.gif' />FullMetaObjectByString类型是tFullMetaObject个表索引类型是varchar2(30) 列表2:MetaDataPkg包规范标准 用如下方式建立或更新MetaDataPkg: cEnabled constant char(7) := ’ENABLED’; cDisabled constant char(8) := ’DISABLED’; cUsable constant char(6) := ’USABLE’; cUnusable constant char(8) := ’UNUSABLE’; cValid constant char(5) := ’VALID’; cInvalid constant char(7) := ’INVALID’; cTable constant char(5) := ’TABLE’; cView constant char(4) := ’VIEW’; cIndex constant char(5) := ’INDEX’; cConstra constant char(10) := ’CONSTRAINT’; cTrigger constant char(7) := ’TRIGGER’; cLobType constant char(3) := ’LOB’; cClobType constant char(4) := ’CLOB’; cBlobType constant char(4) := ’BLOB’; cPackage constant char(7) := ’PACKAGE’; cPackageBody constant char(12) := ’PACKAGE BODY’; cProcedure constant char(9) := ’PROCEDURE’; cFunction constant char(8) := ’FUNCTION’; cSequence constant char(8) := ’SEQUENCE’; cSynonym constant char(7) := ’SYNONYM’; cType constant char(4) := ’TYPE’; cColumn constant char(6) := ’COLUMN’; cJavaSource constant char(11) := ’JAVA SOURCE’; cJavaClass constant char(10) := ’JAVA CLASS’; cYes constant char(3) := ’YES’; cNo constant char(2) := ’NO’; cPKConsType constant char(1) := ’P’; cUNConsType constant char(1) := ’U’; cFKConsType constant char(1) := ’R’; cCKConsType constant char(1) := ’C’; cDropStorage constant char(12) := ’DROP STORAGE’; cReuseStorage constant char(13) := ’REUSE STORAGE’; cCascade constant char(19) := ’CASCADE CONSTRAINTS’; cNoCascade constant char(10) := ’NO CASCADE’; cEnable constant char(6) := ’ENABLE’; cNovalidate constant char(10) := ’NOVALIDATE’; cRely constant char(4) := ’RELY’; cNoRely constant char(6) := ’NORELY’; cValidated constant char(9) := ’VALIDATED’; cNotValidated constant char(13) := ’NOT VALIDATED’; cLogging constant char(7) := ’LOGGING’; cNoLogging constant char(9) := ’NOLOGGING’; cParallel constant char(8) := ’PARALLEL’; cNoParallel constant char(10) := ’NOPARALLEL’; cNull constant char(4) := ’NULL’; cNotNull constant char(8) := ’NOT NULL’; cDefault constant char(7) := ’DEFAULT’; cSYSPrefix constant char(4) := ’SYS_’; cDoubleQuote constant char(1) := ’"’; subtype tString is varchar2(30); subtype tDBString is varchar2(255); subtype tDBLongString is varchar2(4000); subtype tLongString is varchar2(32767); type tArrayLongString is table of tLongString index by pls_eger; type tMetaObject is record ( aName tString, aType tString, aLogging tString, aParallel tString, aStatus tString, aValidated tString, aRely tString, aDDLString tLongString ); type tArrayMetaObject is table of tMetaObject index by pls_eger; type tFullMetaObject is record ( aTable tMetaObject, aIndexes tArrayMetaObject, aConstras tArrayMetaObject, aTriggers tArrayMetaObject ); type tArrayFullMetaObjectByString is table of tFullMetaObject index by varchar2(30); procedure Load ( pTable in tString, pForce in boolean := false ); procedure Re ( pTable in tString ); procedure Re; function GetMeta ( pTable in tString, pForce in boolean := false ) tFullMetaObject; function GetMeta tArrayFullMetaObjectByString; procedure SetMeta ( pTable in tString, pFullMetaObject in tFullMetaObject ); procedure SetMeta ( pArrayFullMetaObjectByString in tArrayFullMetaObjectByString ); procedure Show ( pTable in tString ); procedure Show; end MetaDataPkg; 上面类型对象是作为元数据存储器用于存放多个表完整元数据信息集合所有上面类型都包含在包规范标准中(列表2所示)我还介绍了下面些API: · MetaDataPkg.Load过程:把特定表元数据信息载入存储器中 · MetaDataPkg.GetMeta:它从存储器中检索tFullMetaObject类型对象 · MetaDataPkg.SetMeta过程(重载):把对象元数据存储到存储器中 · MetaDataPkg.Re过程(重载):对存储器复位 · MetaDataPkg.Show过程(重载):显示存储器内容 实现所有这些事务代码 列表3显示了MetaDataPkg包主体代码些解释私有过程SetEnvironment包含了所有环境设置代码在包化部分会这个过程因此在每个对话中它都只执行次符合你需求(你希望在开头设置次)包提供了用于设置环境参数API:DBMS_METADATA.SET_TRANSFORM_PARAM过程 列表3:MetaDataPkg包主体 vMetaData tArrayFullMetaObjectByString; procedure SetEnvironment is begin dbms_metadata._transform_param( dbms_metadata.session_transform, ’PRETTY’, false); dbms_metadata.SET_TRANSFORM_PARAM( dbms_metadata.session_transform, ’SEGMENT_ATTRIBUTES’, true); dbms_metadata._transform_param( dbms_metadata.session_transform, ’STORAGE’, true); dbms_metadata._transform_param( dbms_metadata.session_transform, ’TABLESPACE’, true); dbms_metadata._transform_param( dbms_metadata.session_transform, ’CONSTRAINTS’, false); dbms_metadata._transform_param( dbms_metadata.session_transform, ’REF_CONSTRAINTS’, false); dbms_metadata._transform_param( dbms_metadata.session_transform, ’CONSTRAINTS_AS_ALTER’, false); end SetEnvironment; procedure Pr ( pString varchar2, pLineSize positive := 80 ) is vLineSize pls_eger := least(nvl(pLineSize, 80), 255); begin dbms_output.enable(1000000); (length(pString) > vLineSize) then dbms_output.put_line(substr(pString, 1, vLineSize)); Pr(substr(pString, pLineSize + 1), vLineSize); dbms_output.put_line(pString); end ; end Pr; procedure Show ( pMetaObject in tMetaObject ) is begin dbms_output.put_line(’***’); dbms_output.put_line(’Name: ’ pMetaObject.aName); 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); pr(’DDL String: ’ pMetaObject.aDDLString, 255); dbms_output.put_line(’***’); end Show; function GetDDL ( pName in tString, pType in tString ) tLongString is vClob clob; vLongStrings tArrayLongString; vFullLength pls_eger := 0; vOffSet pls_eger := 0; vLength pls_eger := 0; begin vClob := dbms_metadata.get_ddl(pType, upper(pName)); vFullLength := dbms_lob.GetLength(vClob); for nIndex in 1..ceil(vFullLength / 32767) loop vOffSet := vLength + 1; vLength := least(vFullLength - (nIndex - 1) * 32767, 32767); dbms_lob.read(vClob, vLength, vOffSet, vLongStrings(nIndex)); vLongStrings(nIndex) := replace(vLongStrings(nIndex), cDoubleQuote user cDoubleQuote ’.’, ’’); vLongStrings(nIndex) :=ltrim(rtrim(replace(vLongStrings(nIndex), chr(10), ’’))); end loop; (dbms_lob.isOpen(vClob) > 0) then dbms_lob.close(vClob); end ; vLongStrings(1); end GetDDL; function ObjectExists ( pObjectName in tString, pObjectType in tString, pTableName in tString := null ) boolean is vCount pls_eger := 0; vObjectName tString := ltrim(rtrim(pObjectName)); vObjectType tString := upper(ltrim(rtrim(pObjectType))); vTableName tString := upper(ltrim(rtrim(pTableName))); begin when vObjectType = cColumn then select count(*) o vCount from Dual where exists (select ’1’ from user_tab_columns where column_name = upper(vObjectName) and table_name = vTableName); when vObjectType = cConstra then select count(*) o vCount from Dual where exists (select ’1’ from user_constras where constra_name = upper(vObjectName) and table_name = vTableName); when vObjectType in (cJavaSource, cJavaClass) then select count(*) o vCount from Dual where exists (select ’1’ from user_objects where object_name = vObjectName and object_type = vObjectType); select count(*) o vCount from Dual where exists (select ’1’ from user_objects where object_name = upper(pObjectName) and object_type = vObjectType); end ; (vCount > 0); end ObjectExists; procedure Load ( pTable in tString, pForce in boolean := false ) is vFullMetaObject tFullMetaObject; vTable tString := upper(ltrim(rtrim(pTable))); vCount pls_eger := 0; begin (not vMetaData.exists(vTable) or nvl(pForce, false)) then not ObjectExists(pTable, cTable) then raise_application_error(-20500, ’Unable to load metadata for ’ nvl(pTable, ’NULL’) ’. ’ ’Table does not exist.’ ); end ; for rec in (select table_name, logging, ltrim(rtrim(degree)) as degree, partitioned, backed_up from user_tables where table_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); end loop; for rec in (select index_name, uniqueness, logging, ltrim(rtrim(degree)) as degree, status from user_indexes where table_name = vTable and index_type != cLobType) loop vCount := vCount + 1; vFullMetaObject.aIndexes(vCount).aName := rec.index_name; 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); end loop; vCount := 0; for rec in (select constra_name,constra_type,status,search_condition,validated,rely from user_constras where table_name = vTable order by decode(constra_type, cPKConsType, 10, cUNConsType, 20, cFKConsType, 30, cCKConsType, 40, 100), constra_name) loop vCount := vCount + 1; vFullMetaObject.aConstras(vCount).aName := rec.constra_name; vFullMetaObject.aConstras(vCount).aType := rec.constra_type; vFullMetaObject.aConstras(vCount).aLogging := null; vFullMetaObject.aConstras(vCount).aParallel := null; vFullMetaObject.aConstras(vCount).aStatus := rec.status; vFullMetaObject.aConstras(vCount).aValidated := rec.validated; vFullMetaObject.aConstras(vCount).aRely := rec.rely; substr(rec.constra_name, 1, length(cSYSPrefix)) = cSYSPrefix and upper(rec.search_condition) like ’%IS ’ cNotNull ’%’ then vFullMetaObject.aConstras(vCount).aDDLString := ’ALTER TABLE ’ cDoubleQuote vFullMetaObject.aTable.aName cDoubleQuote ’ ’ ’MODIFY ’ replace(rec.search_condition, ’IS ’ cNotNull, cNotNull) ( when vFullMetaObject.aConstras(vCount).aValidated = cNotValidated then ’ ’ cNovalidate ’’end); vFullMetaObject.aConstras(vCount).aDDLString := GetDDL(rec.constra_name, cConstra); end ; end loop; SetMeta(pTable, vFullMetaObject); end ; end Load; procedure Re ( pTable in tString ) is begin vMetaData.delete(pTable); end Re; procedure Re is begin vMetaData.delete; end Re; function GetMeta ( pTable in tString, pForce in boolean := false ) tFullMetaObject is begin (not vMetaData.exists(pTable) or nvl(pForce, false)) then Load(pTable, pForce); not vMetaData.exists(pTable) then raise_application_error(-20501, ’Unable to find metadata for ’ pTable ’ in repository.’); end ; end ; vMetaData(pTable); end GetMeta; function GetMeta tArrayFullMetaObjectByString is begin vMetaData; end GetMeta; procedure SetMeta ( pTable in tString, pFullMetaObject in tFullMetaObject ) is begin vMetaData(pTable) := pFullMetaObject; end SetMeta; procedure SetMeta ( pArrayFullMetaObjectByString in tArrayFullMetaObjectByString ) is begin vMetaData := pArrayFullMetaObjectByString; end SetMeta; procedure Show ( pTable in tString ) is vFullMetaObject tFullMetaObject; begin (vMetaData.exists(pTable)) then dbms_output.enable(1000000); vFullMetaObject := vMetaData(pTable); dbms_output.put_line(’Start Full Object: ’ pTable); dbms_output.put_line(’Start Table: ’ pTable); Show(vFullMetaObject.aTable); dbms_output.put_line(’Finish Table: ’ pTable); dbms_output.put_line(’Start Indexes: ’ pTable); (vFullMetaObject.aIndexes.count > 0) then for nIndex in vFullMetaObject.aIndexes.first..vFullMetaObject.aIndexes.last loop Show(vFullMetaObject.aIndexes(nIndex)); end loop; end ; dbms_output.put_line(’Finish Indexes: ’ pTable); dbms_output.put_line(’Start Constras: ’ pTable); (vFullMetaObject.aConstras.count > 0) then for nIndex in vFullMetaObject.aConstras.first..vFullMetaObject.aConstras.last loop Show(vFullMetaObject.aConstras(nIndex)); end loop; end ; dbms_output.put_line(’Finish Constras: ’ pTable); dbms_output.put_line(’Start Triggers: ’ pTable); (vFullMetaObject.aTriggers.count > 0) then for nIndex in vFullMetaObject.aTriggers.first..vFullMetaObject.aTriggers.last loop Show(vFullMetaObject.aTriggers(nIndex)); end loop; end ; dbms_output.put_line(’Finish Triggers: ’ pTable); dbms_output.put_line(’Finish Full Object: ’ pTable); end ; end Show; procedure Show is vTable tString; begin vMetaData.count > 0 then dbms_output.put_line(’Total Meta Objects: ’ to_char(vMetaData.count)); vTable := vMetaData.first; while (vTable is not null) loop Show(vTable); vTable := vMetaData.next(vTable); end loop; end ; end Show; begin SetEnvironment; end MetaDataPkg; 下面代码防止输出信息采用缩排或换行格式化: dbms_metadata._transform_param(dbms_metadata.session_transform, ’PRETTY’, false); 下面 3行输出片段属性(物理属性、存储属性、表空间、日志等)、数据表存储、表空间子句和索引对象定义: dbms_metadata._transform_param(dbms_metadata.session_transform, ’SEGMENT_ATTRIBUTES’, true); dbms_metadata._transform_param(dbms_metadata.session_transform, ’STORAGE’, true); dbms_metadata._transform_param(dbms_metadata.session_transform, ’TABLESPACE’, true); 明确地指定所有物理、存储和日志属性是非常重要--否则它们会被设为默认值而这个值可能和原始设置值区别 SetEnvironment过程最后 3行防止所有非参考和参考约束被包含到表DDL中它还禁止独立ALTER TABLE语句(假如必要还可以禁止CREATE INDEX语句)来生成数据表约束: dbms_metadata._transform_param(dbms_metadata.session_transform, ’CONSTRAINTS’, false); dbms_metadata._transform_param(dbms_metadata.session_transform, ’REF_CONSTRAINTS’, false); dbms_metadata._transform_param(dbms_metadata.session_transform, ’CONSTRAINTS_AS_ALTER’, false); 为了达到最大灵活性最好分别提取数据表、索引和约束对象定义并保证它们彼此都相互独立通过这种办法你可以控制这些对象建立次序 MetaDataPkg包主要工作部分是MetaDataPkg.GetDDLMetaDataPkg.GetDDL包含了列表1代码扩展版本添加到里面是提取超过32767个DDL串能力它可以帮助处理分区数据表定义--随着分区数量增长它可能变得很长这也是GetDDL代码把DDL串分析并载入每个长达32767串原因目前代码版本只返回第个元素因此你需要修改这段代码把该转换为tMetaObject记录类型属性这样就答应它处理长于32767串当然这种情况非常少见 使用MetaDataPkg.GetMeta API可以得到每个特定数据表完整元数据对象这个API接受两个参数:pTable它是表名称;pForce布尔型标记当pForce被设置为TRUE时候它强迫元数据从Oracle数据字典中检索接着把元数据载入存储器中--不管是否预备好了但是默认值是FALSE因此第个把元数据载入存储器中并返回tFullMetaObject类型对象后面GetMeta简单地从存储器中检索元数据 使用MetaDataPkg包 为了演示如何使用MetaDataPkg包我建立了小段匿名代码块它把EmpTest表中元数据载入元数据存储器中并输出它内容 下面就是匿名PL/SQL代码块: declare vTable MetaDataPkg.tString := ’EmpTest’; vRunStartTime number; begin vRunStartTime := dbms_utility.get_time; MetaDataPkg.Load(vTable, true); MetaDataPkg.Show; dbms_output.put_line(’Time Elapsed: ’ to_char((dbms_utility.get_time - vRunStartTime) / 100) ’ sec.’); end; 列表4显示了前面代码输出信息 你可以看到这段代码把EmpTest数据表和其索引、约束全部元数据信息载入到存储器中并在秒钟的内把它检索出来了你现在拥有了个用于开发自动解决方案API了它可以进行任何数据维护操作包括更名、转换和删除数据库对象 0
相关文章
读者评论
发表评论 |