侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

SQL Server中Check约束的学习教程

数据库  /  管理员 发布于 5年前   302

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) violated02290. 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) violated02290. 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_nameADD 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_supplieradd constraint check_tb_suppliercheck (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) violated02290. 00000 - "check constraint (%s.%s) violated"*Cause:  The values being inserted do not satisfy the named check

3. 启用CHECK约束

3.1 语法

ALTER TABLE table_nameENABLE 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.简单查询
查询优化器在生成执行计划之前有一个阶段叫做代数树优化,比如说下面这个简单查询:

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

那么Check约束呢?

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

图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 testPartitionViewASSELECT * FROM Test2007UNIONSELECT * FROM Test2008 SELECT * FROM testPartitionViewWHERE [ReviewDate]='2007-01-01' SELECT * FROM testPartitionViewWHERE [ReviewDate]='2008-01-01' SELECT * FROM testPartitionViewWHERE [ReviewDate]='2010-01-01'

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

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


4. 禁用CHECK约束

4.1 语法

ALTER TABLE table_nameDISABLE CONSTRAINT constraint_name;

4.2 示例

--禁用约束ALTER TABLE tb_supplier DISABLE CONSTRAINT check_tb_supplier_id;

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

--查看约束的详细信息selectconstraint_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_nameDROP CONSTRAINT constraint_name;

6.2 示例

ALTER TABLE tb_supplierDROP CONSTRAINT check_tb_supplier_id;


  • 上一条:
    SqlLoader怎么使用
    下一条:
    详解SQL中drop、delete和truncate的异同
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 分库分表的目的、优缺点及具体实现方式介绍(0个评论)
    • DevDB - 在 VS 代码中直接访问数据库(0个评论)
    • 在ubuntu系统中实现mysql数据存储目录迁移流程步骤(0个评论)
    • 在mysql中使用存储过程批量新增测试数据流程步骤(0个评论)
    • php+mysql数据库批量根据条件快速更新、连表更新sql实现(0个评论)
    • 近期文章
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2017-06
    • 2017-08
    • 2017-09
    • 2017-10
    • 2017-11
    • 2018-01
    • 2018-05
    • 2018-10
    • 2018-11
    • 2020-02
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2020-07
    • 2020-08
    • 2020-09
    • 2021-02
    • 2021-04
    • 2021-07
    • 2021-08
    • 2021-11
    • 2021-12
    • 2022-02
    • 2022-03
    • 2022-05
    • 2022-06
    • 2022-07
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-07
    • 2023-08
    • 2023-10
    • 2023-11
    • 2023-12
    • 2024-01
    • 2024-03
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客