在 Oracle 10g 中通过数据库链接复制元数据

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1636154/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 19:18:13  来源:igfitidea点击:

Copying metadata over a database link in Oracle 10g

oraclemetadatadblink

提问by Tunde

Thanks in advance for your help experts.

在此先感谢您的帮助专家。

I want to be able to copy over database objects from database A into database B with a procedure created on database B.

我希望能够使用在数据库 B 上创建的过程将数据库对象从数据库 A 复制到数据库 B。

I created a database link between the two and have tweaked the get_ddl function of the dbms_metadata to look like this:

我在两者之间创建了一个数据库链接,并将 dbms_metadata 的 get_ddl 函数调整为如下所示:

create or replace function GetDDL
   (
      p_name in MetaDataPkg.t_string
      p_type in MetaDataPkg.t_string

   )
      return MetaDataPkg.t_longstring
   is
      -- clob
      v_clob clob;

      -- array of long strings
      c_SYSPrefix        constant char(4)  := 'SYS_';
      c_doublequote      constant char(1)  := '"';   
      v_longstrings metadatapkg.t_arraylongstring;
      v_schema      metadatapkg.t_string;
      v_fullength   pls_integer := 0;
      v_offset      pls_integer := 0;
      v_length      pls_integer := 0;

   begin

        SELECT DISTINCT OWNER
        INTO v_schema
        FROM all_objects@ENTORA
        where object_name = upper(p_name);

      -- get DDL
      v_clob := dbms_metadata.get_ddl(p_type, upper(p_name), upper(v_schema));

      -- get CLOB length
      v_fullength := dbms_lob.GetLength(v_clob);

      for nIndex in 1..ceil(v_fullength / 32767)
      loop
         v_offset := v_length + 1;
         v_length := least(v_fullength - (nIndex - 1) * 32767, 32767);

         dbms_lob.read(v_clob, v_length, v_offset, v_longstrings(nIndex));


          -- Remove table's owner from DDL string:

         v_longstrings(nIndex) := replace(
            v_longstrings(nIndex),
            c_doublequote || user || c_doublequote || '.',
            ''
         );


          -- Remove the following from DDL string:
          -- 1) "new line" characters (chr(10))
          -- 2) leading and trailing spaces

         v_longstrings(nIndex) :=
         ltrim(rtrim(replace(v_longstrings(nIndex), chr(10), '')));         
      end loop;

      -- close CLOB
      if (dbms_lob.isOpen(v_clob) > 0)
      then
         dbms_lob.close(v_clob);
      end if;

      return v_longstrings(1);

   end GetDDL;

so as to remove the schema prefix that usually comes with metadata. I get a null value whenever I run this function over the database link with the following queries.

以便删除通常带有元数据的模式前缀。每当我通过以下查询在数据库链接上运行此函数时,我都会得到一个空值。

select getddl( 'TABLE', 'TABLE1') from user_tables@ENTORA where table_name = 'TABLE1';

select getddl('TABLE', 'TABLE1') from user_tables@ENTORA where table_name = 'TABLE1';

select getddl( 'TABLE', 'TABLE1') from dual@ENTORA;

select getddl('TABLE', 'TABLE1') from dual@ENTORA;

t_string is varchar2(30) t_longstring is varchar2(32767) and type t_ArrayLongString is table of t_longstring

t_string 是 varchar2(30) t_longstring 是 varchar2(32767) 类型 t_ArrayLongString 是 t_longstring 的表

I would really appreciate it if any one could help. Many thanks.

如果有人可以提供帮助,我将不胜感激。非常感谢。

采纳答案by Tunde

CREATE OR REPLACE function DEMO_FN
(object_type varchar2, table_name varchar2) return varchar2 
is 

v_longstrings varchar2(32223);
c_doublequote      constant char(1)  := '"';  
begin 
v_longstrings := dbms_metadata.get_ddl(object_type,table_name);

-- Remove double quotes from DDL string:
v_longstrings := replace(v_longstrings, c_doublequote || user || c_doublequote || '.','');

-- Remove the following from DDL string:
          -- 1) "new line" characters (chr(10))
          -- 2) leading and trailing spaces
v_longstrings := ltrim(rtrim(replace(v_longstrings, chr(10), '')));
return v_longstrings; 
end;
/

Please note that the signed in schema must have the SELECT_CATALOG_ROLE to execute this function.

请注意,登录模式必须具有 SELECT_CATALOG_ROLE 才能执行此功能。

An example is

一个例子是

select demo_fn@db_link('TABLE','TABLE_NAME') FROM DUAL;

select demo_fn@db_link('TABLE','TABLE_NAME') FROM DUAL;

回答by Jaroslav

this works fine

这工作正常

declare
  v_ddl  clob;
  V_DDL_PART varchar2(4000);
begin
    for I in 0 .. 50 loop
      select DBMS_LOB.SUBSTR@db_link(DBMS_METADATA.GET_DDL@db_link('TABLE','MYTABLE'),(4000 * I + 1)) into V_DDL_PART from dual@db_link;
      V_DDL := V_DDL || V_DDL_PART;
    end loop;
end;

回答by a1ds

This work fine, small bug fixed:

这个工作正常,修复了小错误:

declare
    v_ddl  clob;
    V_DDL_PART varchar2(4000);
begin
    for I in 0 .. 10 loop
        select DBMS_LOB.SUBSTR@LINK(
            DBMS_METADATA.GET_DDL@LINK('TABLE','NAME','SCHEMA'),
            4000,(4000 * I + 1)) into V_DDL_PART from dual@LINK;
        V_DDL := V_DDL || V_DDL_PART;
    end loop;
    dbms_output.put_line(v_ddl);
end;

回答by Erich Kitzmueller

I hope I get the syntax right, but I think it should be v_clob := [email protected]_ddl(...)instead of v_clob := dbms_metadata.get_ddl(...)

我希望我的语法正确,但我认为它应该v_clob := [email protected]_ddl(...)代替v_clob := dbms_metadata.get_ddl(...)