sql - 如何从表中查找列的约束名称并使用单个查询将其删除
问题描述
我需要找到一列的约束名称,并且我需要使用单个 select 语句将其删除。如果不可能,那么替代方法是什么
我需要将此查询提供给另一个人,以便当他运行查询时,它会自动找到特定表的列的约束名称,然后将其删除.. 无需硬编码任何东西
解决方案
这是一个示例 - 一个测试表,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
数据类型 for 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
好的; 列上的约束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>
结论:你不应该盲目地放弃约束。
推荐阅读
- swift - 将渐变应用于 UICollectionViewCell 中的标签
- spring-boot - 如何为 Spring Boot 测试定义 spring.config.name?
- python - Tkinter - 如何改进“grab_set()”方法的行为?
- python - 通过函数Python传递变量
- python - 如何将 Pandas 中的重复编号列转换为单数、非编号列?
- mongodb - 20 个 mongodbs 服务器集中到只有 1 个
- php - 致命错误:未捕获的错误:类 'App\DB\QueryBuilder'
- r - 如何解释 QQ 图上的 y 轴
- regex - 替换两个字符串之间所有出现的字符
- java - 具有多个登录页面的 Spring Security 只需要订单 1