как найти имя ограничения столбца из таблицы и удалить его одним запросом - PullRequest
0 голосов
/ 28 июня 2019

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

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

Ответы [ 2 ]

2 голосов
/ 28 июня 2019

Вот пример - тестовая таблица с ограничением NOT NULL, которое нужно удалить.

SQL> CREATE TABLE test
  2  (
  3     id    NUMBER PRIMARY KEY,
  4     name  VARCHAR2 (10) NOT NULL,            --> this constraint should be dropped
  5     sex   VARCHAR2 (1) CHECK (sex IN ('Y', 'N'))
  6  );

Table created.

SQL> SELECT table_name, column_name, constraint_name
  2    FROM user_cons_columns
  3   WHERE table_name = 'TEST';

TABLE_NAME                     COLUMN_NAM CONSTRAINT_NAME
------------------------------ ---------- ------------------------------
TEST                           NAME       SYS_C0069006     --> this one
TEST                           SEX        SYS_C0069007
TEST                           ID         SYS_C0069008

SQL>

Функция (из-за LONG типа данных для USER_CONSTRAINTS.SEARCH_CONDITION, чтобы мы могли проверить, является ли он NOT NULL):

SQL> CREATE OR REPLACE FUNCTION f_sc (par_constraint_name IN VARCHAR2)
  2     RETURN VARCHAR2
  3  IS
  4     l_search_condition  user_constraints.search_condition%TYPE;
  5  BEGIN
  6     SELECT search_condition
  7       INTO l_search_condition
  8       FROM user_constraints
  9      WHERE constraint_name = par_constraint_name;
 10
 11     RETURN l_search_condition;
 12  END;
 13  /

Function created.

SQL>

Процедура, которая будет принимать имя таблицы и имя столбца; если есть ограничение NOT NULL, оно будет удалено. В противном случае ничего не произойдет:

SQL> CREATE OR REPLACE PROCEDURE p_dropcon (par_table_name   IN VARCHAR2,
  2                                         par_column_name  IN VARCHAR2)
  3  IS
  4     l_con  user_cons_columns.constraint_name%TYPE;
  5  BEGIN
  6     SELECT a.constraint_name
  7       INTO l_con
  8       FROM user_constraints a
  9            JOIN user_cons_columns b ON b.constraint_name = a.constraint_name
 10      WHERE     a.table_name = UPPER (par_table_name)
 11            AND b.column_name = UPPER (par_column_name)
 12            AND INSTR (UPPER (f_sc (a.constraint_name)), 'IS NOT NULL') > 0;
 13
 14     EXECUTE IMMEDIATE
 15           'alter table '
 16        || DBMS_ASSERT.sql_object_name (par_table_name)
 17        || ' drop constraint '
 18        || l_con;
 19  EXCEPTION
 20     WHEN NO_DATA_FOUND
 21     THEN
 22        -- There's no NOT NULL constraint on that column
 23        NULL;
 24  END;
 25  /

Procedure created.

SQL>

Тестирование:

SQL> EXEC p_dropcon('test', 'name');

PL/SQL procedure successfully completed.

SQL> SELECT table_name, column_name, constraint_name
  2    FROM user_cons_columns
  3   WHERE table_name = 'TEST';

TABLE_NAME                     COLUMN_NAM CONSTRAINT_NAME
------------------------------ ---------- ------------------------------
TEST                           SEX        SYS_C0069007
TEST                           ID         SYS_C0069008

OK; ограничение на столбец NAME было удалено. Как насчет ID?

SQL> EXEC p_dropcon('test', 'id');

PL/SQL procedure successfully completed.

SQL> SELECT table_name, column_name, constraint_name
  2    FROM user_cons_columns
  3   WHERE table_name = 'TEST';

TABLE_NAME                     COLUMN_NAM CONSTRAINT_NAME
------------------------------ ---------- ------------------------------
TEST                           SEX        SYS_C0069007
TEST                           ID         SYS_C0069008

SQL>

Ничего не произошло, как ожидалось.


Однако (хотя это вряд ли произойдет), если вы создали собственное проверочное ограничение, содержащее строку поиска, IS NOT NULL, например.

SQL> CREATE TABLE test
  2  (
  3     id    NUMBER PRIMARY KEY,
  4     name  VARCHAR2 (10) NOT NULL,
  5     sex   VARCHAR2 (1) CHECK (sex IN ('IS NOT NULL'))     --> this
  6  );

Table created.

SQL>

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

SQL> SELECT table_name, column_name, constraint_name
  2    FROM user_cons_columns
  3   WHERE table_name = 'TEST';

TABLE_NAME                     COLUMN_NAM CONSTRAINT_NAME
------------------------------ ---------- ------------------------------
TEST                           NAME       SYS_C0069012
TEST                           SEX        SYS_C0069013
TEST                           ID         SYS_C0069014

SQL> EXEC p_dropcon('test', 'sex');

PL/SQL procedure successfully completed.

SQL> SELECT table_name, column_name, constraint_name
  2    FROM user_cons_columns
  3   WHERE table_name = 'TEST';

TABLE_NAME                     COLUMN_NAM CONSTRAINT_NAME
------------------------------ ---------- ------------------------------
TEST                           NAME       SYS_C0069012
TEST                           ID         SYS_C0069014

SQL>

Вывод: вы не должны отбрасывать ограничения вслепую.

0 голосов
/ 28 июня 2019

Просто предоставьте следующий запрос в одном из скриптов .sql клиенту, где клиенту просто нужно изменить имя таблицы.

Вы также можете использовать процедуру или другой известный метод выполнения SQL, который может выполнить следующий код:

BEGIN
    FOR I IN (
        SELECT
            TABLE_NAME,
            COLUMN_NAME,
            NULLABLE
        FROM
            USER_TAB_COLUMNS
        WHERE
            TABLE_NAME = 'TEST'
            AND NULLABLE = 'N'
    ) LOOP
        EXECUTE IMMEDIATE 'ALTER TABLE '
                          || I.TABLE_NAME
                          || ' MODIFY '
                          || I.COLUMN_NAME
                          || ' NULL ';
    END LOOP;
END;
/

Вы можете увидеть демоверсию db <> fiddle .

Ура !!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...