我可以使用 DBMS_METADATA 从 DDL 中剥离 SUPPLEMENTAL LOG GROUP 吗?
Can I use DBMS_METADATA to strip off the SUPPLEMENTAL LOG GROUP from a DDL?
我想获取一个 table 的 DDL 并从中创建另一个。目前我有这样的东西:
v_stmt := 'select dbms_metadata.get_ddl(''TABLE'', ''' || original_table || ''') from dual';
execute immediate v_stmt into v_stmt ;
v_stmt := REGEXP_REPLACE(v_stmt, '(' || original_table || ')', new_table, 1, 1);
execute immediate v_stmt;
当前 table 已生成补充日志组。我不想要这个,或者更确切地说,当我尝试创建时,我遇到了以下错误。
ORA-30567: name already used by an existing log group
如何删除 SUPPLEMENTAL LOG GROUP?是否可以使用类似下面的方法或有其他解决方案?
dbms_metadata.set_transform_param(dbms_metadata.session_transform,'PARTITIONING',false);
我想我也可以使用 REGEXP_REPLACE 但我也不知道该怎么做。
作为参考,生成的语句包含如下内容:
...
SUPPLEMENTAL LOG GROUP "SCHEM_TAB0123434" ("CUSTOMERKEY", "VALID", "VERSION", "WHENMODIFIED") ALWAYS,
...
我相信 SET_TRANSFORM_PARAM 帮不上忙。
您可以尝试 REGEXP_REPLACE:
`v_stmt := regexp_replace(v_stmt, ',\s*supplemental\s+log\s+group\s+"[^"]+"\s*\("[^"]+"(,\s*"[^"]+")*\)\s*always\s*', '',1, 1,'i');`
您似乎无法完全摆脱它,但是如果您使用不同的 dbms_metadata
子程序,您可以将补充日志记录子句拆分成单独的语句并跳过它们。
fetch_ddl
过程为您提供嵌套的 table 单个 DDL 语句;您可以将其与 set_transform_param()
调用结合起来,将约束作为 alter
语句拉出——这也适用于补充日志子句。您还可以更改 table 名称作为提取调用的一部分,而不是稍后手动替换它,使用 set_remap_param()
.
如果我创建一个带有补充日志记录的虚拟 table:
create table t42 (
id number,
log_this varchar2(10),
constraint pk_t42 primary key (id),
supplemental log group t42_log_group (log_this) always
);
然后我可以打开上下文句柄,为 table 名称应用过滤器,然后进行转换;然后遍历 DDL 并选择要使用的内容和要跳过的内容:
set serveroutput on;
declare
l_original_table user_tables.table_name%type := 'T42';
l_new_table user_tables.table_name%type := 'NEW_T42';
l_context pls_integer;
l_modify pls_integer;
l_transform pls_integer;
l_ddls sys.ku$_ddls;
l_ddl clob;
begin
l_context := dbms_metadata.open('TABLE');
-- to look for the specific table you are interested in
dbms_metadata.set_filter(l_context, 'NAME', l_original_table);
l_modify := dbms_metadata.add_transform(l_context, 'MODIFY');
-- to change the table name in the generated DDL
dbms_metadata.set_remap_param(l_modify, 'REMAP_NAME', l_original_table, l_new_table,
'TABLE');
l_transform := dbms_metadata.add_transform(l_context, 'DDL');
-- for brevity
dbms_metadata.set_transform_param(l_transform, 'SEGMENT_ATTRIBUTES', false);
-- to split constraints and supplemental logging into separtate DDLs
dbms_metadata.set_transform_param(l_transform, 'CONSTRAINTS_AS_ALTER', true);
l_ddls := dbms_metadata.fetch_ddl(l_context);
for i in l_ddls.first..l_ddls.last loop
l_ddl := l_ddls(i).ddltext;
if dbms_lob.instr(l_ddl, 'SUPPLEMENTAL LOG GROUP') > 0 then
dbms_output.put_line('Skipping DDL: ' || dbms_lob.substr(l_ddl, 4000, 1));
continue;
end if;
dbms_output.put_line('Using DDL: ' || dbms_lob.substr(l_ddl, 4000, 1));
dbms_output.new_line;
-- execute immediate l_ddl;
end loop;
dbms_metadata.close(l_context);
end;
/
对于那个假人 table 显示:
Using DDL: CREATE TABLE "MY_SCHEMA"."NEW_T42"
( "ID" NUMBER,
"LOG_THIS" VARCHAR2(10)
)
Using DDL:
ALTER TABLE "MY_SCHEMA"."NEW_T42" ADD CONSTRAINT "PK_T42" PRIMARY KEY ("ID")
USING INDEX ENABLE
Skipping DDL:
ALTER TABLE "MY_SCHEMA"."NEW_T42" ADD SUPPLEMENTAL LOG GROUP "T42_LOG_GROUP" ("LOG_THIS") ALWAYS
PL/SQL procedure successfully completed.
保留基础 create table
以及除匹配 'SUPPLEMENTAL LOG GROUP'
字符串的任何其他语句。
在这种情况下,我的 PK 约束名称也会成为问题 - 第一个 create
DDL 将 运行 OK execute immediate
取消注释,但 alter
当前未被跳过的将获得 ORA-02264。如果你有一个合理的命名约定,你可以添加额外的 set_remap_param
调用来改变它们,也许。
我想获取一个 table 的 DDL 并从中创建另一个。目前我有这样的东西:
v_stmt := 'select dbms_metadata.get_ddl(''TABLE'', ''' || original_table || ''') from dual';
execute immediate v_stmt into v_stmt ;
v_stmt := REGEXP_REPLACE(v_stmt, '(' || original_table || ')', new_table, 1, 1);
execute immediate v_stmt;
当前 table 已生成补充日志组。我不想要这个,或者更确切地说,当我尝试创建时,我遇到了以下错误。
ORA-30567: name already used by an existing log group
如何删除 SUPPLEMENTAL LOG GROUP?是否可以使用类似下面的方法或有其他解决方案?
dbms_metadata.set_transform_param(dbms_metadata.session_transform,'PARTITIONING',false);
我想我也可以使用 REGEXP_REPLACE 但我也不知道该怎么做。
作为参考,生成的语句包含如下内容:
...
SUPPLEMENTAL LOG GROUP "SCHEM_TAB0123434" ("CUSTOMERKEY", "VALID", "VERSION", "WHENMODIFIED") ALWAYS,
...
我相信 SET_TRANSFORM_PARAM 帮不上忙。
您可以尝试 REGEXP_REPLACE:
`v_stmt := regexp_replace(v_stmt, ',\s*supplemental\s+log\s+group\s+"[^"]+"\s*\("[^"]+"(,\s*"[^"]+")*\)\s*always\s*', '',1, 1,'i');`
您似乎无法完全摆脱它,但是如果您使用不同的 dbms_metadata
子程序,您可以将补充日志记录子句拆分成单独的语句并跳过它们。
fetch_ddl
过程为您提供嵌套的 table 单个 DDL 语句;您可以将其与 set_transform_param()
调用结合起来,将约束作为 alter
语句拉出——这也适用于补充日志子句。您还可以更改 table 名称作为提取调用的一部分,而不是稍后手动替换它,使用 set_remap_param()
.
如果我创建一个带有补充日志记录的虚拟 table:
create table t42 (
id number,
log_this varchar2(10),
constraint pk_t42 primary key (id),
supplemental log group t42_log_group (log_this) always
);
然后我可以打开上下文句柄,为 table 名称应用过滤器,然后进行转换;然后遍历 DDL 并选择要使用的内容和要跳过的内容:
set serveroutput on;
declare
l_original_table user_tables.table_name%type := 'T42';
l_new_table user_tables.table_name%type := 'NEW_T42';
l_context pls_integer;
l_modify pls_integer;
l_transform pls_integer;
l_ddls sys.ku$_ddls;
l_ddl clob;
begin
l_context := dbms_metadata.open('TABLE');
-- to look for the specific table you are interested in
dbms_metadata.set_filter(l_context, 'NAME', l_original_table);
l_modify := dbms_metadata.add_transform(l_context, 'MODIFY');
-- to change the table name in the generated DDL
dbms_metadata.set_remap_param(l_modify, 'REMAP_NAME', l_original_table, l_new_table,
'TABLE');
l_transform := dbms_metadata.add_transform(l_context, 'DDL');
-- for brevity
dbms_metadata.set_transform_param(l_transform, 'SEGMENT_ATTRIBUTES', false);
-- to split constraints and supplemental logging into separtate DDLs
dbms_metadata.set_transform_param(l_transform, 'CONSTRAINTS_AS_ALTER', true);
l_ddls := dbms_metadata.fetch_ddl(l_context);
for i in l_ddls.first..l_ddls.last loop
l_ddl := l_ddls(i).ddltext;
if dbms_lob.instr(l_ddl, 'SUPPLEMENTAL LOG GROUP') > 0 then
dbms_output.put_line('Skipping DDL: ' || dbms_lob.substr(l_ddl, 4000, 1));
continue;
end if;
dbms_output.put_line('Using DDL: ' || dbms_lob.substr(l_ddl, 4000, 1));
dbms_output.new_line;
-- execute immediate l_ddl;
end loop;
dbms_metadata.close(l_context);
end;
/
对于那个假人 table 显示:
Using DDL: CREATE TABLE "MY_SCHEMA"."NEW_T42"
( "ID" NUMBER,
"LOG_THIS" VARCHAR2(10)
)
Using DDL:
ALTER TABLE "MY_SCHEMA"."NEW_T42" ADD CONSTRAINT "PK_T42" PRIMARY KEY ("ID")
USING INDEX ENABLE
Skipping DDL:
ALTER TABLE "MY_SCHEMA"."NEW_T42" ADD SUPPLEMENTAL LOG GROUP "T42_LOG_GROUP" ("LOG_THIS") ALWAYS
PL/SQL procedure successfully completed.
保留基础 create table
以及除匹配 'SUPPLEMENTAL LOG GROUP'
字符串的任何其他语句。
在这种情况下,我的 PK 约束名称也会成为问题 - 第一个 create
DDL 将 运行 OK execute immediate
取消注释,但 alter
当前未被跳过的将获得 ORA-02264。如果你有一个合理的命名约定,你可以添加额外的 set_remap_param
调用来改变它们,也许。