2013-09-08 2 views
3

Я работаю над Oracle 11g. Я получаю запрос пользователя, например.Как переназначить исходную таблицу запроса на другую таблицу программно

SELECT mycolumn 
    FROM myschema.mytable 

Запрос может быть произвольно сложным с подзапросами и не известен заранее. Теперь я хочу изменить запрос и перенаправить все использования исходной таблицы mytable на другую таблицу mytable_mod независимо от того, где в запросе или в подзапросе они возникают.

Конечно, вы можете найти строку для возникновения mytable, но это весьма ненадежный подход, так как другие части запроса может иметь такое же имя (столбец, например, или некоторые комментарии)

I попытался создать представление с этим утверждением и использовать 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» или в какой-либо другой структурированной форме?

+0

Какова техническая причина изменения QUERY? Почему вы не можете изменить структуру? Например, переименуйте 'myschema.mytable' в' myschema.mytable_old', 'создайте или замените представление myschema.mytable как select * из myschema.mytable_mod' и сохраните запрос неповрежденным? –

+0

Я понимаю, что вы делаете немного лучше, но условный аспект все еще неясен; о каких условиях мы говорим здесь? – Ben

+0

Я использую запрос, потому что пользователь должен увидеть, что что-то изменилось. Когда пользователь ссылается на mytable, он всегда должен получать оригинальную таблицу. – markop

ответ

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, по умолчанию, ложь. Используя ALTER PROCEDURE заявление, мы можем установить флаг верно:

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 с некоторыми примерами, а также.

+0

Я не уверен, что полностью понял ваш подход, но мне кажется, что мне нужно знать запросы, в которых я хочу сделать переопределение таблицы заранее, что в моей проблеме не так. Я уточню вопрос, чтобы уточнить. – markop