Создайте процедуру в oracle DB для поиска и удаления ограничений внешнего ключа для определенных таблиц - PullRequest
0 голосов
/ 26 сентября 2018

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

CREATE OR REPLACE PROCEDURE removeConstraintsForTable(vTableName IN varchar2) IS
BEGIN
cName VARCHAR(2048);
sql_stmt VARCHAR2(2048);
CURSOR cur IS
          SELECT DISTINCT CONSTRAINT_NAME
          FROM ALL_CONSTRAINTS WHERE OWNER= sys_context('userenv','current_schema')
          AND TABLE_NAME = vTableName AND CONSTRAINT_TYPE='R';
BEGIN
    OPEN cur;
    LOOP
    FETCH cur INTO cName;
    EXIT WHEN cur%notfound;
    sql_stmt := CONCAT(CONCAT(CONCAT('ALTER TABLE ',vTableName),CONCAT(' DROP FOREIGN KEY ',cName)),';');
    SELECT sql_stmt FROM dual;
    INSERT INTO TEMP(Name) VALUES(sql_stmt);
    COMMIT;
    END LOOP;
END
/


CALL removeConstraintsForTable('table1');
CALL removeConstraintsForTable('table2');
CALL removeConstraintsForTable('table3');
CALL removeConstraintsForTable('table4');
COMMIT;

Ответы [ 2 ]

0 голосов
/ 26 сентября 2018

У вас есть лишний BEGIN в самом начале процедуры, а в последнем END отсутствует точка с запятой.Вы не должны действительно использовать VARCHAR, и вы все равно можете объявить переменную cName, используя словарь данных;однако неявный цикл будет проще, как и использование оператора конкатенации || вместо вложенных вызовов CONCAT(), и сгенерированный оператор не должен заканчиваться точкой с запятой:

create or replace procedure removeconstraintsfortable(p_table_name in varchar2) is
  sql_stmt varchar2(2048);
begin
  for rec in (
    select owner, constraint_name
    from all_constraints
    where owner = sys_context('userenv','current_schema')
    and table_name = p_table_name
    and constraint_type = 'R'
  )
  loop
    sql_stmt := 'ALTER TABLE "' || rec.owner || '"."' || p_table_name || '"'
      || ' DROP CONSTRAINT "' || rec.constraint_name || '"';

    insert into temp(name) values(sql_stmt);
  end loop;
  commit;
end;
/

Как указано в комментарияхсгенерированный оператор должен быть drop constraint.

Я не уверен, почему вы вставляете в таблицу или где вы выполняете оператор, но вы можете сделать все это в одном, если хотите:

create or replace procedure removeconstraintsfortable(p_table_name in varchar2) is
  sql_stmt varchar2(2048);
begin
  for rec in (
    select owner, constraint_name
    from all_constraints
    where owner = sys_context('userenv','current_schema')
    and table_name = p_table_name
    and constraint_type = 'R'
  )
  loop
    sql_stmt := 'ALTER TABLE "' || rec.owner || '"."' || p_table_name || '"'
      || ' DROP CONSTRAINT "' || rec.constraint_name || '"';

    dbms_output.put_line(sql_stmt);
    execute immediate sql_stmt;
  end loop;
end;
/

Вызов dbms_output просто показывает вам сгенерированные операторы до того, как execute immediate выполнит его, ну, немедленно.

Quick demo;очень простая установка таблицы:

create table t42 (id number primary key);
create table t43 (id number references t42 (id));

select table_name, constraint_name, constraint_type
from all_constraints
where table_name in ('T42', 'T43');

TABLE_NAME                     CONSTRAINT_NAME                C
------------------------------ ------------------------------ -
T43                            SYS_C00138153                  R
T42                            SYS_C00138152                  P

Затем вызовите процедуру, которая показывает сгенерированный оператор:

set serveroutput on
exec removeConstraintsForTable('T43');

ALTER TABLE "STACKOVERFLOW"."T43" DROP CONSTRAINT "SYS_C00138153"

PL/SQL procedure successfully completed.

, а затем проверьте, что ограничение прошло:

select table_name, constraint_name, constraint_type
from all_constraints
where table_name in ('T42', 'T43');

TABLE_NAME                     CONSTRAINT_NAME                C
------------------------------ ------------------------------ -
T42                            SYS_C00138152                  P
0 голосов
/ 26 сентября 2018

Я исправил ряд синтаксических проблем для вас.Попробуйте это.

CREATE OR REPLACE PROCEDURE removeConstraintsForTable(vTableName IN varchar2) IS
    cName VARCHAR2(30); -- identifiers are max 30 chars
    sql_stmt VARCHAR2(2048);
    CURSOR cur IS
          SELECT DISTINCT CONSTRAINT_NAME
          FROM USER_CONSTRAINTS 
          WHERE TABLE_NAME = vTableName AND CONSTRAINT_TYPE='R';
BEGIN
    OPEN cur;
    LOOP
    FETCH cur INTO cName;
    EXIT WHEN cur%notfound;
    sql_stmt := 'ALTER TABLE ' || vTableName || ' DROP CONSTRAINT ' || cName;
    INSERT INTO RANGERADMIN1.TEMP(Name) VALUES(sql_stmt);
    END LOOP;
    COMMIT;
END removeConstraintsForTable;
/

call removeConstraintsForTable('table1');
call removeConstraintsForTable('table2');
call removeConstraintsForTable('table3');
call removeConstraintsForTable('table4');
-- COMMIT; -- not necessary
...