Вот пример - тестовая таблица с ограничением 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>
Вывод: вы не должны отбрасывать ограничения вслепую.