удалить индекс или ограничение, не зная его имени для Oracle - PullRequest
6 голосов
/ 25 января 2012

В базе данных оракула у меня есть внешний ключ, не зная его имени, только column_name и reference_column_name. Я хочу написать сценарий sql, который должен удалить этот внешний ключ, если он существует, поэтому этот код я использую:

declare
 fName varchar2(255 char);
begin
 SELECT x.constraint_name into fName FROM all_constraints x
 JOIN all_cons_columns c ON
 c.table_name = x.table_name AND c.constraint_name = x.constraint_name
 WHERE x.table_name = 'MY_TABLE_NAME' AND x.constraint_type = 'R' AND c.column_name ='MY_COLUMN_NAME';
end;

Вывод этого скрипта - «анонимный блок завершен», поэтому он был успешным, но когда я добавляю опускаемую часть:

declare
 fName varchar2(255 char);
begin
 SELECT x.constraint_name into fName FROM all_constraints x
 JOIN all_cons_columns c ON
 c.table_name = x.table_name AND c.constraint_name = x.constraint_name
 WHERE x.table_name = 'MY_TABLE_NAME' AND x.constraint_type = 'R' AND c.column_name ='MY_COLUMN_NAME';
 if (fName != '') THEN
  alter table MY_TABLE_NAME drop constraint fName;
 end if;
end;

Тогда я получаю это:

Отчет об ошибке: ORA-06550: строка 9, столбец 5: PLS-00103: обнаружен символ «ALTER» при ожидании одного из следующих действий:

начать регистр объявлять выход для goto if loop mod null pragma Повышение Возврат выберите обновление, а с << закрыть текущее удаление извлекать блокировку вставить открытую откат для слияния труб 06550. 00000 - «строка% s, столбец% s: \ n% s» * Причина: обычно ошибка компиляции PL / SQL. * Действие: </p>

Так может кто-нибудь сказать мне, в чем здесь проблема?

Я также пытался поместить все в функцию:

declare
  function getFName return varchar2 is
    fName varchar2(255 char);
  begin
   SELECT x.constraint_name into fName FROM all_constraints x
   JOIN all_cons_columns c ON
   c.table_name = x.table_name AND c.constraint_name = x.constraint_name
   WHERE x.table_name = 'MY_TABLE_NAME' AND x.constraint_type = 'R' AND c.column_name ='MY_COLUMN_NAME';

   return fName;
  end;
begin
  if getFName() != '' then
   alter table all_events drop constraint getFName(); 
  end if;
end; 

В результате возникла та же ошибка, вызванная оператором "alter table"

Этот тоже не помог:

alter table all_events drop constraint
   (SELECT x.constraint_name into fName FROM all_constraints x
   JOIN all_cons_columns c ON
   c.table_name = x.table_name AND c.constraint_name = x.constraint_name
   WHERE x.table_name = 'MY_TABLE_NAME' AND x.constraint_type = 'R' AND c.column_name ='MY_COLUMN_NAME');

Вывод был:

Отчет об ошибке: Ошибка SQL: ORA-02250: отсутствует или недопустимо имя ограничения 02250. 00000 - «отсутствует или недопустимо имя ограничения» * Причина: имя ограничения отсутствует или недействительно. * Действие: укажите допустимое имя идентификатора для имени ограничения.

Для сервера sql (MS SQL) это так просто сделать. Просто объявите переменную с @ и установите ее, после этого просто используйте ее. На оракуле я понятия не имею, что это не работает ...

Ответы [ 2 ]

6 голосов
/ 25 января 2012

Ваша оригинальная версия в основном в порядке, за исключением того, что вы не можете напрямую выполнить DDL в блоке PL / SQL;скорее, вы должны обернуть его в EXECUTE IMMEDIATE:

execute immediate 'alter table MY_TABLE_NAME drop constraint "' || fName || '"';

Это было бы верно, даже если имя ограничения было известно во время компиляции, но это вдвойне верно в вашем случае, так как fName это не имя ограничения, а переменная, содержащая имя ограничения.

Кроме того, это:

if (fName != '') THEN

недопустимо / значимо, поскольку в Oracle '' означает NULL.Вместо этого вы должны написать

IF fName IS NOT NULL THEN

.

2 голосов
/ 03 февраля 2013

Это как отбросить все ограничения, набранные «R» для столбца:

begin
    FOR rec IN (SELECT x.constraint_name fName FROM all_constraints x
        JOIN all_cons_columns c ON
        c.table_name = x.table_name AND c.constraint_name = x.constraint_name
        WHERE x.table_name = 'MY_TABLE_NAME' AND x.constraint_type = 'R' AND c.column_name ='MY_COLUMN_NAME')
    LOOP
        EXECUTE IMMEDIATE 'ALTER TABLE MY_TABLE_NAME DROP CONSTRAINT "' || rec.fName || '"';
    END LOOP;
end;
...