Есть ли способ объединить оператор SELECT и ALTER (объединение DML и DDL)? - PullRequest
2 голосов
/ 17 апреля 2019

Я хотел переименовать индекс динамически.

Предыстория: Oracle автоматически создает индекс для материализованных представлений, если базовая таблица имеет первичный ключ (я думаю?). Имя этого индекса меняется каждый раз, когда MV удаляется и создается. Я хочу переименовать этот индекс.

Мой план состоял в том, чтобы выбрать имя индекса и вставить его в оператор alter.

Select table_owner||'.'||INDEX_Name 
  from all_indexes
 WHERE table_name = 'mytable' 
   and table_owner = 'myuser' 
   and uniqueness = 'UNIQUE';
ALTER INDEX (that select statement here) 
  RENAME TO abetterindexname

Но это бросило эту ошибку:

ORA-00953: missing or invalid index name

Я разобрался с ответом перед публикацией. Вот что сработало:

DECLARE
avariable  varchar2(100);
BEGIN
Select table_owner||'.'||INDEX_Name 
  into avariable  
  from all_indexes
 WHERE table_name = 'mytable' 
   and table_owner = 'myuser' 
   and uniqueness = 'UNIQUE';
execute immediate 'ALTER INDEX '||avariable||' RENAME TO abetterindexname';
 END;

Источник: https://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:7038453003289. - Мне пришлось создать строку для оператора немедленного выполнения.

Если кто-нибудь знает, как это сделать только с SQL, мне было бы интересно.

Ответы [ 2 ]

2 голосов
/ 17 апреля 2019

вы не можете сделать это в SQL. SQL это язык запросов. Вы можете использовать только DDL как

ALTER INDEX <old name> RENAME TO <new name>

или plsql с динамическим sql

begin
  execute immediate 'ALTER INDEX '||<old name>||' RENAME TO '|| <new name>;
end;
1 голос
/ 19 апреля 2019

Можно запустить DDL в чистом операторе SQL, используя новую функцию 12c WITH.

Нижеследующий оператор является обычным оператором SELECT, использующим общее табличное выражение.Но это общее табличное выражение ссылается на функцию, которая выполняет оператор SQL.Этот код не требует установки каких-либо объектов и может быть запущен в контексте SELECT.

with function exec_sql(p_sql varchar2) return number is
    pragma autonomous_transaction;
begin
    execute immediate p_sql;
    return 1;
end;
select exec_sql('ALTER INDEX '||owner||'.'||index_name||' RENAME TO abetterindexname')
from all_indexes
where table_name = 'MYTABLE'
    and table_owner = owner
    and uniqueness = 'UNIQUE';
/

Но не рекомендуется запускать такие изменения как часть инструкции SELECT.Oracle не гарантирует точного порядка и количества выполнений частей оператора SELECT (хотя на практике мы обычно можем это выяснить).Гораздо безопаснее выполнить изменение в анонимном блоке PL / SQL.Этот метод, вероятно, полезен только в ситуациях, когда мы имеем ограниченный доступ к базе данных, например, инструмент, который выполняет только операторы SELECT.

...