我正在研究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中的文本标记。我的想法是
DBMS_METADATA.CONVERT
将xml转换回ddl语句。但正如我所说,xml不包含sql查询结构本身。有人知道如何将sql语句结构化为“xml对象”或其他结构化形式吗?
答案 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也有一些例子。