如何以编程方式将查询的源表重新映射到另一个表

时间:2013-09-08 10:50:59

标签: oracle plsql

我正在研究Oracle 11g。我收到用户提供的查询,例如

SELECT mycolumn
  FROM myschema.mytable

查询可能与子查询任意复杂,并且事先不知道。 现在,我想更改查询并将源表mytable的所有用法重定向到另一个表mytable_mod,无论它们出现在查询或子查询中的哪个位置。

当然,您可以在字符串中搜索mytable的出现次数,但这是一种非常不可靠的方法,因为查询的其他部分可能具有相同的名称(例如,列或某些注释)

我尝试使用该语句创建一个视图,并使用DBMS_METADATA进行分析:

CREATE OR REPLACE VIEW MYSCHEMA.TESTVIEW as 
SELECT mycolumn FROM myschema.mytable

使用DBMS_METADATA,您可以像这样替换架构(经过一些准备工作):

dbms_metadata.set_remap_param(handler, 'REMAP_SCHEMA', 
                             'MYSCHEMA', 'MY_OTHER_SCHEMA');

使用REMAP_NAME代替REMAP_SCHEMA,您可以替换对象名称。但是这两种方法只引用视图名称而不是视图查询中使用的对象。所以结果将是

CREATE OR REPLACE VIEW MY_OTHER_SCHEMA.TESTVIEW as 
SELECT mycolumn FROM myschema.mytable

另一个想法是将create view语句输出为XML对象。我得到所有列定义和视图名称,但查询本身只是xml中的文本标记。我的想法是

  1. 查询解压缩为xml
  2. 通过查看标签来替换我想要的对象
  3. 使用DBMS_METADATA.CONVERT将xml转换回ddl语句。
  4. 但正如我所说,xml不包含sql查询结构本身。有人知道如何将sql语句结构化为“xml对象”或其他结构化形式吗?

1 个答案:

答案 0 :(得分:1)

这取决于你的条件,但一种方法是使用conditional compilation;虽然这意味着您必须完成所有代码,但在某些情况下它可能非常有用。这不是100%清楚这是否会对你有所帮助;你首先提到“以编程方式”,但继续说你想要搜索字符串,在这种情况下它可能会。

条件编译使用一组静态布尔语句来改变编译时的源代码。编译器标志前面加上$$,您可以控制构造$IF-$THEN-$ELSE发生的事情。

例如,如果您想要更改从您的过程中选择的表,可能如下所示:

SQL> create or replace procedure do_something (
  2       p_curs out sys_refcursor ) is
  3
  4  begin
  5
  6     $if $$right_schema $then
  7        open p_curs for
  8          select * from user_tables;
  9     $else
 10        open p_curs for
 11          select * from all_tables;
 12     $end
 13
 14  end;
 15  /

Procedure created.

如果您使用DBMS_METADATA查看该过程,那么它看起来就像上面那样;但是,DBMS_PREPROCESSOR你可以看到它是如何被编译的:

SQL> begin
  2    dbms_preprocessor.print_post_processed_source (
  3      object_type => 'PROCEDURE',
  4      schema_name => user,
  5      object_name => 'DO_SOMETHING');
  6  end;
  7  /
procedure do_something (
p_curs out sys_refcursor ) is
begin
open p_curs for
select * from all_tables;
end;

PL/SQL procedure successfully completed.

这是因为编译器标志$$right_schema默认为false。使用ALTER PROCEDURE语句,我们可以将标志设置为true:

alter procedure do_something compile plsql_ccflags = 'right_schema:TRUE';

现在打印已处理的来源会显示以下内容:

SQL> begin
  2    dbms_preprocessor.print_post_processed_source (
  3      object_type => 'PROCEDURE',
  4      schema_name => user,
  5      object_name => 'DO_SOMETHING');
  6  end;
  7  /
procedure do_something (
p_curs out sys_refcursor ) is
begin
open p_curs for
select * from user_tables;
end;

PL/SQL procedure successfully completed.

Oracle Base还有a useful article也有一些例子。