亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 數據庫 > Oracle > 正文

Oracle中提取和存儲數據庫對象的DDL

2024-08-29 13:46:41
字體:
來源:轉載
供稿:網友
從對象(例如數據庫表、索引、約束、觸發器等)中提取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_constraints、user_cons_columns等)中提取數據庫對象的元數據,接著為特定的對象構造DDL命令。這些腳本的一個問題是,它們通常是SQL*Plus腳本,它會生成客戶端文本文件,而這個文件不能被服務器端代碼訪問。它們的主要問題有:

  · 不完整:不能提取所有的選項,并組合進DDL語句中。

  · 過時了:這些腳本通常不支持Oracle最新的數據庫特性--分區(partitioning)、基于函數的索引、自動段空間治理(ASSM)等。這些腳本可能崩潰或生成錯誤的DDL語句。

  問題總結:盡管有大量的從Oracle數據字典中提取數據庫對象元數據的腳本,但是它們中的大多數要么不完整,要么過期了。

  解決方案:使用DBMS_METADATA程序包,學習如何用最佳的、沒有錯誤的和易于維護的方式執行上面的事務。

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

  Oracle數據庫采用補充PL/SQL程序包的形式提供了豐富的預先包裝好的API。Oracle 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 integer not null,
lastName varchar2(30) not null,
firstName varchar2(20) not null,
job varchar2(9) ’
hireDate date ’
isActive number(1)
constraint EmpTest_CK1
check (isActive in (0,1)) ,
salary number(9,2) ,
commision number(9,2) ,
deptNo number(2) ,
constraint EmpTest_PK
PRimary key (empNo),
constraint EmpTest_AK1
unique (lastName, firstName)
);

create index EmpTest_HireDate_Salary
on EmpTest
(
salary,
hireDate
);
  運行上面的腳本之后,就建立了一個帶有三個索引(兩個唯一的和一個不唯一的索引)的EmpTest表:

select index_name, index_type, uniqueness
from user_indexes
where table_name = ’EMPTEST’;

索引名稱索引類型唯一性EMPTEST_AK1NORMALUNIQUEEMPTEST_HIREDATE_SALARYNORMALNONUNIQUEEMPTEST_PKNORMALUNIQUE
  EmpTest表還包括六個約束:

  · 一個主鍵-EmpTest_PK

  · 一個備用鍵-EmpTest_AK

  · 一個檢查約束-EmpTest_CK1

  · 系統生成的(SYS_*)三個非空的約束,名稱如下:

約束名稱約束類型索引名稱SYS_C002144065C  SYS_C002144066C  SYS_C002144067C  EMPTEST_CK1C  EMPTEST_PKP EMPTEST_PKEMPTEST_AK1U EMPTEST_AK1
  現在我們執行匿名的PL/SQL代碼塊來調用DBMS_METADATA.GET_DDL函數,檢索數據表的定義。

  DBMS_OUTPUT程序包只能輸出最長為255個字符的字符串,由于在處理數據表的DDL字符串的時候太輕易超過這個限制,所以這是一個問題。為了解決這個問題,我們使用了本地過程Show()(列表1所示)。

  列表1:調用DBMS_METADATA.GET_DDL()函數的PL/SQL代碼塊

declare
vClob clob;
vLongString varchar2(32767);
vOffSet pls_integer := 0;
vLength pls_integer := 0;
vTable varchar2(30) := ’EmpTest’;

procedure Show (pVariable varchar2, pLineSize pls_integer := 80)
is
begin
dbms_output.enable(1000000);
if (length(pVariable) > pLineSize)
then
dbms_output.put_line(substr(pVariable, 1, pLineSize));
Show(substr(pVariable, pLineSize + 1), pLineSize);
else
dbms_output.put_line(pVariable);
end if;
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
if (dbms_lob.isOpen(vClob) > 0)
then
dbms_lob.close(vClob);
end if;
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_integer;
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_integer;
  下一步需要建立一個記錄類型,它包含了數據表表自身(aTable)的tMetaObject屬性和三個tArrayMetaObject屬性:一個用于索引(aIndexes),一個用于約束(aConstraints),一個用于觸發器(aTriggers):

type tFullMetaObject is record
(
aTable tMetaObject,
aIndexes tArrayMetaObject,
aConstraints tArrayMetaObject,
aTriggers tArrayMetaObject
);
  tFullMetaObject對象類型保存了單個表的全部對象的元數據。最后,位于頂層的類型是tFullMetaObject數組。TarrayFullMetaObjectByString類型是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’;
cConstraint 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_integer;

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

type tFullMetaObject is record
(
 aTable tMetaObject,
 aIndexes tArrayMetaObject,
 aConstraints tArrayMetaObject,
 aTriggers tArrayMetaObject
);

type tArrayFullMetaObjectByString is table of tFullMetaObject
index by varchar2(30);

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

procedure Reset
(
 pTable in tString
);

procedure Reset;

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

function GetMeta
return 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.Reset過程(重載的):對存儲器復位。

  · MetaDataPkg.Show過程(重載的):顯示存儲器的內容。
實現所有這些事務的代碼

  列表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了,它可以進行任何數據維護操作,包括更名、轉換和刪除數據庫對象。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
深夜福利日韩在线看| 奇米4444一区二区三区| 亚洲欧美一区二区三区四区| 亚洲欧美国产一本综合首页| 91精品国产九九九久久久亚洲| 亚洲第一色在线| 日韩电影中文字幕一区| 欧美电影在线免费观看网站| 2019最新中文字幕| 国产精品久久国产精品99gif| 欧美日韩激情视频8区| 国产精品成av人在线视午夜片| 国产精品久久久一区| 亚洲片在线观看| 欧美国产日韩在线| 国内伊人久久久久久网站视频| 欧美性极品xxxx做受| 色与欲影视天天看综合网| 久久精品亚洲94久久精品| 国产在线精品一区免费香蕉| 国产一区二区三区在线播放免费观看| 国产精品91在线观看| 黑人巨大精品欧美一区二区一视频| 中国人与牲禽动交精品| 国产精品成人aaaaa网站| 欧美日韩aaaa| 成人淫片在线看| 日韩av免费网站| 美女av一区二区三区| 欧美激情二区三区| 国产精品视频精品视频| 日韩欧美在线播放| 日韩视频一区在线| 日本中文字幕成人| 国产日本欧美一区二区三区| 欧美日韩精品二区| 欧洲成人午夜免费大片| 91精品久久久久久久久中文字幕| 国产欧美亚洲精品| 精品国偷自产在线视频| 97成人超碰免| 国产一区欧美二区三区| 91免费的视频在线播放| 亚洲人成电影在线播放| 欧美亚洲伦理www| 欧美成人精品在线播放| 另类少妇人与禽zozz0性伦| 久久精品视频在线观看| 亚洲国产另类久久精品| 97国产精品免费视频| 日韩欧美国产骚| …久久精品99久久香蕉国产| 久久精品美女视频网站| 国产精品精品一区二区三区午夜版| 成人激情免费在线| 日韩电影免费在线观看| 久久中文字幕视频| 国产精品激情av电影在线观看| 亚洲黄在线观看| 国产精品日韩欧美大师| 国产日韩欧美在线视频观看| 成人激情电影一区二区| 久久久97精品| 欧美肥老太性生活视频| 国产精品免费观看在线| 91日韩在线视频| 国产日韩精品在线播放| 久久久女女女女999久久| 精品久久久久久久久中文字幕| 98午夜经典影视| 欧美性生活大片免费观看网址| 国产精品久久久久久一区二区| 欧美色图在线视频| 久久久免费av| 欧美国产日韩视频| 4438全国成人免费| 欧美一级黄色网| 欧美日韩免费一区| 国产乱肥老妇国产一区二| 欧美在线观看www| 亚洲欧洲国产精品| 亚洲天堂av高清| 精品一区二区三区四区在线| 国产精品吴梦梦| 久久久久久久久久久免费精品| 久久久国产精品免费| 亚洲欧美日韩在线高清直播| 最近更新的2019中文字幕| 亚洲电影免费观看| 亚洲国产成人久久综合| 欧美美女操人视频| 欧美理论电影网| 国产成人av网址| 亚洲伊人一本大道中文字幕| 国产精品一区av| 欧美性猛交99久久久久99按摩| 国产亚洲一区二区在线| 国产精品入口日韩视频大尺度| 日韩av电影国产| 亚洲国产精品久久91精品| 欧美亚洲成人免费| 4p变态网欧美系列| 国产精品福利网站| 国产福利精品视频| 欧美老肥婆性猛交视频| 伊人亚洲福利一区二区三区| 国产成人精品一区| 国产成人免费91av在线| 日本乱人伦a精品| 一区二区三区黄色| 日韩高清人体午夜| 久久国产精彩视频| 一区二区三区无码高清视频| 亚洲www永久成人夜色| 成人久久久久久久| 久久伊人91精品综合网站| 久久影视电视剧免费网站清宫辞电视| 国产精品情侣自拍| 国产亚洲一区二区精品| 在线播放日韩av| 亚洲伊人成综合成人网| 亚洲性日韩精品一区二区| 亚洲iv一区二区三区| 国产精品爽黄69天堂a| 国产日本欧美视频| 日韩小视频在线观看| 成人激情视频网| 欧美成人h版在线观看| 色综合影院在线| 91九色蝌蚪国产| 亚洲精品98久久久久久中文字幕| 中日韩美女免费视频网站在线观看| 亚洲欧洲美洲在线综合| 欧美精品中文字幕一区| 国产精品十八以下禁看| 国产精品一区二区久久精品| 全亚洲最色的网站在线观看| 国产精品香蕉国产| 国产精品xxxxx| 欧美国产高跟鞋裸体秀xxxhd| 精品视频中文字幕| 欧美午夜www高清视频| 国产精品免费在线免费| 国产精品免费观看在线| 欧美高跟鞋交xxxxhd| 欧美一区二粉嫩精品国产一线天| 欧美成人高清视频| 欧美寡妇偷汉性猛交| 欧美午夜美女看片| 亚洲精品大尺度| 日韩69视频在线观看| 91国产精品视频在线| 欧美日韩中文字幕在线视频| 日韩h在线观看| 日韩电影中文 亚洲精品乱码| 欧美性高潮床叫视频| 欧美黄色片在线观看| 亚洲精品国产免费| 亚洲欧美日韩一区二区三区在线| 在线看欧美日韩| 日韩高清av一区二区三区| 一本色道久久88综合亚洲精品ⅰ| 久久99国产综合精品女同| 国产精品自在线|