当前位置: 移动技术网 > IT编程>数据库>MSSQL > SQL Server中Check约束的学习教程

SQL Server中Check约束的学习教程

2017年12月08日  | 移动技术网IT编程  | 我要评论

飞达,东营马拉松直播,黄延秋

0.什么是check约束?

check约束指在表的列中增加额外的限制条件。

注: check约束不能在view中定义。check约束只能定义的列必须包含在所指定的表中。check约束不能包含子查询。

创建表时定义check约束

1.1 语法:

create table table_name
(
  column1 datatype null/not null,
  column2 datatype null/not null,
  ...
  constraint constraint_name check (column_name condition) [disable]
);

其中,disable关键之是可选项。如果使用了disable关键字,当check约束被创建后,check约束的限制条件不会生效。


1.2 示例1:数值范围验证

create table tb_supplier
(
 supplier_id    number,
 supplier_name   varchar2(50),
 contact_name   varchar2(60),
 /*定义check约束,该约束在字段supplier_id被插入或者更新时验证,当条件不满足时触发。*/
 constraint check_tb_supplier_id check (supplier_id between 100 and 9999)
);

验证:
在表中插入supplier_id满足条件和不满足条件两种情况:

--supplier_id满足check约束条件,此条记录能够成功插入
insert into tb_supplier values(200, 'dlt','stk');
 
--supplier_id不满足check约束条件,此条记录能够插入失败,并提示相关错误如下
insert into tb_supplier values(1, 'david louis tian','stk');

不满足条件的错误提示:

error report -
sql error: ora-02290: check constraint (502351838.check_tb_supplier_id) violated
02290. 00000 - "check constraint (%s.%s) violated"
*cause:  the values being inserted do not satisfy the named check


1.3 示例2:强制插入列的字母为大写

create table tb_products
(
 product_id    number not null,
 product_name   varchar2(100) not null,
 supplier_id    number not null,
 /*定义check约束check_tb_products,用途是限制插入的产品名称必须为大写字母*/
 constraint check_tb_products
 check (product_name = upper(product_name))
);

验证:
在表中插入product_name满足条件和不满足条件两种情况:

--product_name满足check约束条件,此条记录能够成功插入
insert into tb_products values(2, 'lenovo','2');
--product_name不满足check约束条件,此条记录能够插入失败,并提示相关错误如下
insert into tb_products values(1, 'iphone','1');

不满足条件的错误提示:

sql error: ora-02290: check constraint (502351838.check_tb_products) violated
02290. 00000 - "check constraint (%s.%s) violated"
*cause:  the values being inserted do not satisfy the named check

2. alter table定义check约束

2.1 语法

alter table table_name
add constraint constraint_name check (column_name condition) [disable];

其中,disable关键之是可选项。如果使用了disable关键字,当check约束被创建后,check约束的限制条件不会生效。

2.2 示例准备

drop table tb_supplier;
--创建实例表
create table tb_supplier
(
 supplier_id    number,
 supplier_name   varchar2(50),
 contact_name   varchar2(60)
);

2.3 创建check约束

--创建check约束
alter table tb_supplier
add constraint check_tb_supplier
check (supplier_name in ('ibm','lenovo','microsoft'));

2.4 验证

--supplier_name满足check约束条件,此条记录能够成功插入
insert into tb_supplier values(1, 'ibm','us');
 
--supplier_name不满足check约束条件,此条记录能够插入失败,并提示相关错误如下
insert into tb_supplier values(1, 'dell','ho');

不满足条件的错误提示:

sql error: ora-02290: check constraint (502351838.check_tb_supplier) violated
02290. 00000 - "check constraint (%s.%s) violated"
*cause:  the values being inserted do not satisfy the named check

3. 启用check约束

3.1 语法

alter table table_name
enable constraint constraint_name;

 

3.2 示例

drop table tb_supplier;
--重建表和check约束
create table tb_supplier
(
 supplier_id    number,
 supplier_name   varchar2(50),
 contact_name   varchar2(60),
 /*定义check约束,该约束尽在启用后生效*/
 constraint check_tb_supplier_id check (supplier_id between 100 and 9999) disable
);
 
--启用约束
alter table tb_supplier enable constraint check_tb_supplier_id;

 
3.3使用check约束提升性能

在sql server中,sql语句的执行是依赖查询优化器生成的执行计划,而执行计划的好坏直接关乎执行性能。

在查询优化器生成执行计划过程中,需要参考元数据来尽可能生成高效的执行计划,因此元数据越多,则执行计划更可能会高效。所谓需要参考的元数据主要包括:索引、表结构、统计信息等,但还有一些不是很被注意的元数据,其中包括本文阐述的check约束。
图1.简单查询
查询优化器在生成执行计划之前有一个阶段叫做代数树优化,比如说下面这个简单查询:

20151211155126523.png (414×248)

查询优化器意识到1=2这个条件是永远不相等的,因此不需要返回任何数据,因此也就没有必要扫描表,从图1执行计划可以看出仅仅扫描常量后确定了1=2永远为false后,就可完成查询。

那么check约束呢?

check约束可以确保一列或多列的值符合表达式的约束。在某些时候,check约束也可以为优化器提供信息,从而优化性能,比如看图二的例子。

20151211155147674.png (470×262)

图2.有check约束的列提升查询性能

图2是一个简单的例子,有时候在分区视图中应用check约束也会提升性能,测试代码如下:

create table [dbo].[test2007](
  [productreviewid] [int] identity(1,1) not null,
  [reviewdate] [datetime] not null
) on [primary]
 
go
 
alter table [dbo].[test2007] with check add constraint [ck_test2007] check (([reviewdate]>='2007-01-01' and [reviewdate]'2007-12-31'))
go
 
alter table [dbo].[test2007] check constraint [ck_test2007]
go
 
create table [dbo].[test2008](
  [productreviewid] [int] identity(1,1) not null,
  [reviewdate] [datetime] not null
) on [primary]
 
go
 
alter table [dbo].[test2008] with check add constraint [ck_test2008] check (([reviewdate]>='2008-01-01' and [productreviewid]'2008-12-31'))
go
 
alter table [dbo].[test2008] check constraint [ck_test2008]
go
 
insert into [test2008] values('2008-05-06')
insert into [test2007] values('2007-05-06')
 
create view testpartitionview
as
select * from test2007
union
select * from test2008
 
select * from testpartitionview
where [reviewdate]='2007-01-01'
 
select * from testpartitionview
where [reviewdate]='2008-01-01'
 
select * from testpartitionview
where [reviewdate]='2010-01-01'

我们针对test2007和test2008两张表结构一模一样的表做了一个分区视图。并对日期列做了check约束,限制每张表包含的数据都是特定一年内的数据。当我们对视图进行查询并给定不同的筛选条件时,可以看到结果如图3所示。

20151211155256851.png (669×500)

图3.不同的条件产生不同的执行计划
由图3可以看出,当筛选条件为2007年时,自动只扫描2007年的表,2008年的表也是同样。而当查询范围超出了2007和2008年的check约束后,查询优化器自动判定结果为空,因此不做任何io操作,从而提升了性能。
结论
在check约束条件为简单的情况下(指的是约束限制在单列且表达式中不包含函数),不仅可以约束数据完整性,在很多时候还能够提供给查询优化器信息从而提升性能。


4. 禁用check约束

4.1 语法

alter table table_name
disable constraint constraint_name;

4.2 示例

--禁用约束
alter table tb_supplier disable constraint check_tb_supplier_id;

 
5. 约束详细信息查看
语句:

--查看约束的详细信息
select
constraint_name,--约束名称
constraint_type,--约束类型
table_name,--约束所在的表
search_condition,--约束表达式
status--是否启用
from user_constraints--[all_constraints|dba_constraints]
where constraint_name='check_tb_supplier_id';

6. 删除check约束
6.1 语法

alter table table_name
drop constraint constraint_name;

6.2 示例

alter table tb_supplier
drop constraint check_tb_supplier_id;

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网