3

我正在开发 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

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

  1. 将查询提取为 xml
  2. 通过查看标签替换我想要的对象
  3. 用于DBMS_METADATA.CONVERT将 xml 转换回 ddl 语句。

但正如我所说,xml 本身并不包含 sql 查询结构。有人知道如何将 sql 语句结构化为“xml 对象”或其他结构化形式吗?

4

1 回答 1

1

这取决于您的条件,但一种方法是使用条件编译;尽管这意味着您必须遍历所有代码,但在某些情况下它可能非常有用。这是否对您有帮助还不是 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_METADATAthen 的过程,它看起来就像上面一样;但是,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 有一篇有用的文章,其中包含一些示例。

于 2013-09-08T11:25:12.503 回答