科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道Oracle中提取和存储数据库对象的DDL

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

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

从对象(例如数据库表、索引、约束、触发器等)中提取DDL命令的普通方法涉及到的操作包括从这些对象中提取元数据……

作者:陶刚 来源:天极网 2007年10月22日

关键字: ORACLE

  • 评论
  • 分享微博
  • 分享邮件

在本页阅读全文(共3页)

实现所有这些事务的代码

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

  列表3:MetaDataPkg程序包主体

vMetaData tArrayFullMetaObjectByString;

procedure SetEnvironment
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(
  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);

end SetEnvironment;

procedure Print
(
 pString varchar2,
 pLineSize positive := 80
)
is

vLineSize pls_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, pLineSize + 1), vLineSize);
 else
  dbms_output.put_line(pString);
 end if;

end Print;

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);
print(’DDL String: ’ || pMetaObject.aDDLString, 255);
dbms_output.put_line(’***’);
end Show;

function GetDDL
(
 pName in tString,
 pType in tString
)
return tLongString
is
vClob clob;

vLongStrings tArrayLongString;

vFullLength pls_integer := 0;
vOffSet pls_integer := 0;
vLength pls_integer := 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;

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

return vLongStrings(1);

end GetDDL;

function ObjectExists
(
 pObjectName in tString,
 pObjectType in tString,
 pTableName in tString := null
)
return boolean
is

vCount pls_integer := 0;
vObjectName tString := ltrim(rtrim(pObjectName));
vObjectType tString := upper(ltrim(rtrim(pObjectType)));
vTableName tString := upper(ltrim(rtrim(pTableName)));

begin

case
 when vObjectType = cColumn
 then
 select count(*)
  into vCount
  from Dual
  where exists (select ’1’
  from user_tab_columns
  where column_name = upper(vObjectName)
  and table_name = vTableName);

 when vObjectType = cConstraint
 then
  select count(*)
  into vCount
  from Dual
  where exists (select ’1’
  from user_constraints
  where constraint_name = upper(vObjectName)
  and table_name = vTableName);

when vObjectType in (cJavaSource, cJavaClass)
then
 select count(*)
 into vCount
 from Dual
 where exists (select ’1’
 from user_objects
 where object_name = vObjectName and object_type = vObjectType);

 else
  select count(*)
  into vCount
  from Dual
  where exists (select ’1’
  from user_objects
  where object_name = upper(pObjectName)
  and object_type = vObjectType);
 end case;

return (vCount > 0);

end ObjectExists;

procedure Load
(
 pTable in tString,
 pForce in boolean := false
)
is

vFullMetaObject tFullMetaObject;

vTable tString := upper(ltrim(rtrim(pTable)));
vCount pls_integer := 0;

begin

if (not vMetaData.exists(vTable) or nvl(pForce, false))
 then
 if not ObjectExists(pTable, cTable)
 then
  raise_application_error(-20500,
      ’Unable to load metadata for ’ || nvl(pTable, ’NULL’) ||
      ’. ’ || ’Table does not exist.’
  );
end if;

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 constraint_name,constraint_type,status,search_condition,validated,rely from       user_constraints where table_name = vTable
order by decode(constraint_type,
   cPKConsType, 10,
   cUNConsType, 20,
   cFKConsType, 30,
   cCKConsType, 40,
   100),
constraint_name)
loop
 vCount := vCount + 1;
 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;
 vFullMetaObject.aConstraints(vCount).aValidated := rec.validated;
 vFullMetaObject.aConstraints(vCount).aRely := rec.rely;

 if substr(rec.constraint_name, 1, length(cSYSPrefix)) = cSYSPrefix and
      upper(rec.search_condition) like ’%IS ’ || cNotNull || ’%’
 then
  vFullMetaObject.aConstraints(vCount).aDDLString :=
     ’ALTER TABLE ’ || cDoubleQuote || vFullMetaObject.aTable.aName || cDoubleQuote || ’ ’ ||
     ’MODIFY ’ || replace(rec.search_condition, ’IS ’ || cNotNull, cNotNull) ||
     (case when vFullMetaObject.aConstraints(vCount).aValidated = cNotValidated
      then ’ ’ || cNovalidate
     else ’’end);
 else
  vFullMetaObject.aConstraints(vCount).aDDLString := GetDDL(rec.constraint_name, cConstraint);
 end if;
end loop;

SetMeta(pTable, vFullMetaObject);
end if;
end Load;

procedure Reset
(
 pTable in tString
)
is
begin

vMetaData.delete(pTable);

end Reset;

procedure Reset
is
begin
 vMetaData.delete;
end Reset;

function GetMeta
(
 pTable in tString,
 pForce in boolean := false
)
return tFullMetaObject
is
begin

if (not vMetaData.exists(pTable) or nvl(pForce, false))
then
 Load(pTable, pForce);

 if not vMetaData.exists(pTable)
 then
  raise_application_error(-20501, ’Unable to find metadata for ’ || pTable || ’ in repository.’);
 end if;
end if;

return vMetaData(pTable);

end GetMeta;

function GetMeta
 return tArrayFullMetaObjectByString
is
begin

return 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

if (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);
if (vFullMetaObject.aIndexes.count > 0)
then
for nIndex in vFullMetaObject.aIndexes.first..vFullMetaObject.aIndexes.last
loop
Show(vFullMetaObject.aIndexes(nIndex));
end loop;
end if;
dbms_output.put_line(’Finish Indexes: ’ || pTable);
dbms_output.put_line(’Start Constraints: ’ || pTable);
if (vFullMetaObject.aConstraints.count > 0)
then
for nIndex in vFullMetaObject.aConstraints.first..vFullMetaObject.aConstraints.last
loop
Show(vFullMetaObject.aConstraints(nIndex));
end loop;
end if;
dbms_output.put_line(’Finish Constraints: ’ || pTable);
dbms_output.put_line(’Start Triggers: ’ || pTable);
if (vFullMetaObject.aTriggers.count > 0)
then
for nIndex in vFullMetaObject.aTriggers.first..vFullMetaObject.aTriggers.last
loop
Show(vFullMetaObject.aTriggers(nIndex));
end loop;
end if;
dbms_output.put_line(’Finish Triggers: ’ || pTable);
dbms_output.put_line(’Finish Full Object: ’ || pTable);
end if;
end Show;

procedure Show
is
vTable tString;
begin
 if 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 if;
end Show;

begin
SetEnvironment;
end MetaDataPkg;

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

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(dbms_metadata.session_transform, ’TABLESPACE’, true);

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

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

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);

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

  MetaDataPkg程序包的主要工作部分是MetaDataPkg.GetDDL()函数。MetaDataPkg.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了,它可以进行任何数据维护操作,包括更名、转换和删除数据库对象。

查看本文来源

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章