关于表约束constraint

可以使用disable,enable novalidate,enable validate选项。
可用于检查历史数据是否违反某种业务规则,并找出这些记录!

CREATE TABLE t1 (c1 NUMBER,c2 NUMBER);
INSERT INTO t1 VALUES (1,2);
INSERT INTO t1 VALUES (1,20);
COMMIT;
SELECT * FROM t1;
alter table T1
add constraint ck_t1
check (c2 BETWEEN 18 and 80)
ENABLE novalidate;
create table exceptions(row_id rowid,
owner varchar2(30),
table_name varchar2(30),
constraint varchar2(30));
ALTER TABLE t1 ENABLE Validate CONSTRAINT ck_t1
EXCEPTIONS INTO EXCEPTIONS;
SELECT *
FROM T1
WHERE ROWID IN (SELECT ROW_ID FROM EXCEPTIONS WHERE TABLE_NAME = 'T1')
FOR UPDATE;
TRUNCATE TABLE EXCEPTIONS;
------------------------------------------------------------------------------------------------

constraints 三个需要注意的地方

Ref: http://spaces.msn.com/sunmoonking/
工作许多年,一直没有看重CONSTRINTS的作用,除了用CHECK,NOT NULL,INDEX,等,其他的一般也就看看就过去了。最近把零散的知识整理一下,才发现CONSTRAINTS发展15年来的成熟与重要。
ORACLE提供了众多的constraint,如果没有充分利用这些constraints,那么也就是没有充分利用关系型数据库。如果能了解各种 constraint的各种参数,那么就能减少locking的时间,减少constraint检验数据的时间,减少影响其他应用的时间。
CONSTRAINTS:就是让数据满足某些规则。
CONSTRAINTS TYPE: NOT NULL
UNIQUE
PRIMARY KEY
FOREIGN KEY
CHECK
CONSTRAINTS 不但可以建立在TABLE上,也可以建立在VIEW上,
CONSTRAINTS 的状态:ENABLED/DISABLED
VALIDATED/NOVALIDATED
DEFERRABLE/NON-DEFERRABLE
DEFERRED/IMMEDIATE
RELY/NORELY
constraint只能被difered如果最初定义时是deferrable
view的constraints必须被设置成disabled,novalidated或rely
1. deferrable
一个constraint如果被定义成deferrable那么这个constraints可以在deferred和imediate两种状态相互转换。deferred只在transaction中有效,也就是只可以在transaction过程中使constraint失效,但如果transaction commit的话,transaction会变成immediate。

1* create table cons_parent (id number(10),name varchar2(10))
SQL> /
Table created.
SQL> create table cons_child (id number(10),name varchar2(10));
Table created.
1* alter table cons_parent add primary key (id)
SQL> /
Table altered.
alter table cons_child add constraints chi_fk_par foreign key (id)
references cons_parent(id)
SQL> alter table cons_child add constraints chi_fk_par foreign key (id)
2 references cons_parent(id)
3 /
Table altered.
一个constraints默认是NOT DEFERRABLE的。
1 select constraint_name||' '||deferrable from all_constraints
2* where constraint_name='CHI_FK_PAR'
SQL> /
CONSTRAINT_NAME||''||DEFERRABLE
---------------------------------------------
CHI_FK_PAR NOT DEFERRABLE
NOT DEFERRABLE的不能在deferred和imediate两种状态相互转换
SQL> set constraints chi_fk_par deferred;
SET constraints chi_fk_par deferred
*
ERROR at line 1:
ORA-02447: cannot defer a constraint that is not deferrable
SQL> alter table cons_child drop constraints chi_fk_par;
Table altered.
1 alter table cons_child add constraints chi_fk_par foreign key (id)
2* references cons_parent(id) deferrable
SQL> /
Table altered.
1 select constraint_name||' '||deferrable from all_constraints
2* where constraint_name='CHI_FK_PAR'
SQL> /
CONSTRAINT_NAME||''||DEFERRABLE
---------------------------------------------
CHI_FK_PAR DEFERRABLE
一个constraint如果被定义成deferrable那么这个constraints可以在deferred和imediate两种状态相互转换
SQL> set constraints chi_fk_par immediate;

Constraint set.

1* insert into cons_child values (2,'llll')
SQL> /
insert into cons_child values (2,'llll')
*
ERROR at line 1:
ORA-02291: integrity constraint (SYSTEM.CHI_FK_PAR) violated - parent key not found

SQL> set constraints chi_fk_par deferred;

Constraint set.

SQL> insert into cons_child values (2,'llll');

1 row created.

SQL> set constraints chi_fk_par immediate;
SET constraints chi_fk_par immediate
*
ERROR at line 1:
ORA-02291: integrity constraint (SYSTEM.CHI_FK_PAR) violated - parent key not found

deferred只在transaction中有效,也就是只可以在transaction过程中使constraint失效,但如果transaction commit的话,transaction会变成immediate。

SQL> commit;
commit
*
ERROR at line 1:
ORA-02091: transaction rolled back
ORA-02291: integrity constraint (SYSTEM.CHI_FK_PAR) violated - parent key not found
deferrable会影响CBO的计划,并且正常情况下没有应用的必要,所以建议不要修改,而用系统默认的non deferrable

2. enable/disable validate/novalidate

enable/disable对未来的数据有约束/无约束。

validate/novalidate对已有的数据有约束/无约束。

如果加约束到一个大表,那么ORACLE会LOCK这个表,然后SCAN所有数据,来判断是否符合CONSTRAINT的要求,在繁忙的系统里显然是不合适的。所以用enable novalidate比较合适,因为ORACLE仅仅会LOCK表一小段时间来建立CONSTRAINT,当CONSTRAINT建立后再VALIDATE,这时检验数据是不会LOCK表的。

这方面很多书上都有例子,就不在这里累述了

3.REFERENCE 让人疑惑的地方

1* create table wwm_father (id number,name varchar2(10),primary key (id,name))
SQL> /

Table created.

SQL> create table wwm_child (id number,name varchar2(10),
2 foreign key (id,name) references wwm_father on delete set null);

Table created.

SQL> insert into wwm_father values (6,'wwm');

1 row created.

SQL> insret into wwm_child values (6,'fff');
SP2-0734: unknown command beginning "insret int..." - rest of line ignored.


可以看出,REFERENCE是起作用的。但下面就有点让人疑惑了,似乎ORACLE不用该用这种策略来做,

SQL> insert into wwm_child values (6,null);
1 row created.

SQL> insert into wwm_child values(null,'lll');

1 row created.

1* insert into wwm_child values (null,null)
SQL> /

1 row created.
SQL> select * from wwm_father;

ID NAME
---------- --------------------
6 wwm

SQL> select * from wwm_child;

ID NAME
---------- --------------------
6
lll


SQL> select count(*) from wwm_child;

COUNT(*)
----------
3

可见,如果向CHILD表插入NULL的话,ORACLE默认认为NULL是匹配FATHER表里相关的REFERENCE的字段内容的。因此FOREIGN KEY的COLUMN大家就需要认真考虑是否要设置成NOT NULL了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Oracle 约束是用来保证数据完整性和一致性的规则。它们定义了对中数据的限制,以确保数据的有效性和一致性。 在 Oracle 中,常见的约束包括: 1. 主键约束(Primary Key Constraint):主键约束唯一标识中的每一行数据,并确保主键列的值不为空。 2. 唯一约束(Unique Constraint):唯一约束保证中指定列或列的组合的值是唯一的,但可以包含空值。 3. 外键约束(Foreign Key Constraint):外键约束定义了之间的关系,保证一个中的外键列的值必须在另一个的主键列中存在。 4. 非空约束(Not Null Constraint):非空约束确保指定列的值不为空。 5. 检查约束(Check Constraint):检查约束定义了对中数据的额外条件,只有满足条件的数据才能插入或更新到中。 要在创建时添加约束,可以使用 CREATE TABLE 语句的 CONSTRAINT 子句。例如: ```sql CREATE TABLE employees ( emp_id NUMBER PRIMARY KEY, emp_name VARCHAR2(50) NOT NULL, dept_id NUMBER, salary NUMBER, CONSTRAINT fk_dept FOREIGN KEY (dept_id) REFERENCES departments(dept_id), CONSTRAINT chk_salary CHECK (salary > 0) ); ``` 这个例子创建了一个名为 employees 的,其中包含主键约束(emp_id 列)、非空约束(emp_name 列)、外键约束(dept_id 列引用 departments 的 dept_id 列)和检查约束(salary 列的值必须大于 0)。 除了在创建时定义约束,还可以使用 ALTER TABLE 语句来添加、修改或删除约束
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值