Copia dei metadati su un collegamento al database in Oracle 10g
Domanda
Grazie in anticipo per l'aiuto degli esperti.
Voglio essere in grado di copiare gli oggetti del database dal database A nel database B con una procedura creata sul database B.
Ho creato un collegamento al database tra i due e ho modificato la funzione get_ddl di dbms_metadata in questo modo:
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;
in modo da rimuovere il prefisso dello schema che di solito viene fornito con i metadati. Ottengo un valore null ogni volta che eseguo questa funzione sul collegamento al database con le seguenti query.
seleziona getddl ('TABLE', 'TABLE1') da user_tables @ ENTORA dove table_name = 'TABLE1';
seleziona getddl ('TABLE', 'TABLE1') da dual @ ENTORA;
t_string è varchar2 (30) t_longstring è varchar2 (32767) e digitare t_ArrayLongString è la tabella di t_longstring
Gradirei davvero che qualcuno potesse aiutare. Mille grazie.
Soluzione
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;
/
Si noti che lo schema che ha effettuato l'accesso deve avere SELECT_CATALOG_ROLE per eseguire questa funzione.
Un esempio è
seleziona demo_fn @ db_link ('TABLE', 'TABLE_NAME') DA DUAL;
Altri suggerimenti
funziona bene
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;
Funziona benissimo, piccolo bug corretto:
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;
Spero di ottenere la sintassi corretta, ma penso che dovrebbe essere v_clob: = dbms_metadata@ENTORA.get_ddl (...)
anziché v_clob: = dbms_metadata.get_ddl (. ..)