SQL Server中有关约束(constraint)的一些细节

本文涉及的产品
云数据库 RDS SQL Server,独享型 2核4GB
简介: 原文:SQL Server中有关约束(constraint)的一些细节  本文出处:http://www.cnblogs.com/wy123/p/7350265.html (保留出处并非什么原创作品权利,本人拙作还远远达不到,仅仅是为了链接到原文,因为后续对可能存在的一些错误进行修正或补充,无他...
原文: SQL Server中有关约束(constraint)的一些细节

 

本文出处:http://www.cnblogs.com/wy123/p/7350265.html 
(保留出处并非什么原创作品权利,本人拙作还远远达不到,仅仅是为了链接到原文,因为后续对可能存在的一些错误进行修正或补充,无他)


SQL Server 数据库中的约束(Constrint)是作用是为了保证数据库的完整性和一致性,可以建表的时候指定某个字段要符合某种约束(或者对已有表的字段添加约束),比如唯一性(或者主键)约束,非空约束,默认值约束等
对于具体的约束,可以分为主键(唯一键)约束,默认值约束,检查约束,外键约束等几类。

 

约束的创建方式

  1,建表的时候指定

    如下,可以在建表的时候指定某些字段满足某种约束。

  2,以创建约束的方式指定

    也即在建表的时候没有指定任何约束,在建表之后,以alter table的方式指定某些字段上的约束

    

     

    对于Check或者Default约束,也可以事先定义出来规则(Rule),然后将规则绑定到对应表的字段
     如下分别定义了一个check约束和默认值约束,然后将表的字段绑定到对应的约束,这样做的好处是对于某些复杂的约束,定义好约束之后就可以重用了
    需要注意的是,对于Rule来说,NULL值是不与任何规则冲突的,
    举个例子,如下,虽然把TestConstrint.Sex字段指定了规则Rule_Sex,如果Sex定义的是int,该字段写入数据的时候只能是0或者1,写入2是失败的,
    但是往该字段写入null值是可以的,因为null与规则指定的(0,1)相比没有任何意义(或者没有任何结果)

    

 

 约束的一些特点

    对于建表的时候指定的未命名的约束,SQL Server会自动生成后缀随机的默认的约束名字,为了增加规范性,正常情况下是不允许这么写的,因为我们不希望看到数据库中一堆乱七八脏的命名。

    

     如果是指定约束的名字,看起来就规范多了。

如果是通过定义规则,然后绑定到表的字段的情况下,通过SSMS的图形界面,是看不到约束展开之后的内容的(虽然这个约束是生效的)

 

 数据库约束中那些不容易被注意的坑

    约束看起来非常简单,不管是在建表的时候直接指定,或者是通过alter 表的方式增加约束,看起来都没有任何问题,条条大道通罗马,不过里面还是有一些小坑的。
    一个数据库中的约束不允许重名。
    也就是意味着,不同的表之间,或者表上与自定义约束之间,都不能存在同名的情况,包括主键约束(不能同名),检查约束(check),默认值约束等,都不能同名
    约束的道理跟表一样,一个库的一个schema下中不能定义同名的表一个道理,一个库的一个schema下不能定义同名的约束一样。
    现在也不难理解,为什么sqlserver默认生成的约束的名字,后面是一串随机字符了吧?

    1,表与表之间的约束不能同名

    

    2,表与自定义约束名之间不能同名。

    

    当然有人会说,这有什么,定义的时候报错就知道了,还有更大的坑。
    这里涉及到约束的另一种定义方法,建表的过程中指定命名的主键约束。

 

    比如如下的定义临时表的脚本,看起来没有任何问题,也确实没有任何问题,
    实际中遇到的一个开发人员的问题,编写的存储过程中定义了临时表,定义临时表的时候指定了命名的主键约束(可能是抄的物理表的定义方式),测试通过并发布到生产环境中,一切看起来非常正常。
    发布之后测试了两把,也表现为正常,等到系统真正被用户使用的时候,部分用户反馈系统(涉及到这个功能的地方)偶尔会报错,时而正常,时而不正常(其实这种问题最难诊断的了)。
    监控应用程序会发现,某个时间段之内,发现这个存储过程会连续地报错一种错误,错误原因就是“无法创建索引或者约束”
    开发人员也很委屈,提交完代码之后,明明是测试通过了的,更可恶的是,偶尔会报错,大部分时间是正常的。

    通过观察其代码,然后冷静下来想一想,也不难理解,数据库中的约束是不能同名的,当然临时表生存的临时库也不例外,
    临时表用完就会自动销毁没有错,意味着如果所有的Session都是串行执行,这个完全没有问题。
    但是一旦出现并发调用的情况,不同的Session会同时调用这个存储过程,
    一旦并发调用这个存储过程,不同的Session会创建同一个名字的约束,铁定只有一个会成功,这么看,单线程测试正常,并发上来之后报错也就不难理解了。

    

总结: 

    为了保证数据库的完整性和一致性(外键,本文未涉及),可以使用约束来达到这个目的,但是约束本身有自己的某些规则和特点,它跟其他数据库对象并没有不同的,都不允许同一个schema下存在同名的对象。
    如果没有按照其自身的某些规则来使用,就有可能造成某些潜在的问题。
    为了规范约束的命名,在定义约束名字的时候,要严格遵循简写前缀+schema+tableName+columnName的方式来定义,如果是临时表,禁止定义命名约束。

 

相关实践学习
使用SQL语句管理索引
本次实验主要介绍如何在RDS-SQLServer数据库中,使用SQL语句管理索引。
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情: https://www.aliyun.com/product/rds/sqlserver
目录
相关文章
|
5天前
|
SQL 人工智能 算法
【SQL server】玩转SQL server数据库:第二章 关系数据库
【SQL server】玩转SQL server数据库:第二章 关系数据库
40 10
|
1月前
|
SQL 数据库 数据安全/隐私保护
Sql Server数据库Sa密码如何修改
Sql Server数据库Sa密码如何修改
|
14天前
|
SQL
启动mysq异常The server quit without updating PID file [FAILED]sql/data/***.pi根本解决方案
启动mysq异常The server quit without updating PID file [FAILED]sql/data/***.pi根本解决方案
15 0
|
5天前
|
SQL 算法 数据库
【SQL server】玩转SQL server数据库:第三章 关系数据库标准语言SQL(二)数据查询
【SQL server】玩转SQL server数据库:第三章 关系数据库标准语言SQL(二)数据查询
50 6
|
5天前
|
SQL 存储 数据挖掘
数据库数据恢复—RAID5上层Sql Server数据库数据恢复案例
服务器数据恢复环境: 一台安装windows server操作系统的服务器。一组由8块硬盘组建的RAID5,划分LUN供这台服务器使用。 在windows服务器内装有SqlServer数据库。存储空间LUN划分了两个逻辑分区。 服务器故障&初检: 由于未知原因,Sql Server数据库文件丢失,丢失数据涉及到3个库,表的数量有3000左右。数据库文件丢失原因还没有查清楚,也不能确定数据存储位置。 数据库文件丢失后服务器仍处于开机状态,所幸没有大量数据写入。 将raid5中所有磁盘编号后取出,经过硬件工程师检测,没有发现明显的硬件故障。以只读方式将所有磁盘进行扇区级的全盘镜像,镜像完成后将所
数据库数据恢复—RAID5上层Sql Server数据库数据恢复案例
|
9天前
|
SQL 安全 Java
SQL server 2017安装教程
SQL server 2017安装教程
13 1
|
22天前
|
SQL 存储 Python
Microsoft SQL Server 编写汉字转拼音函数
Microsoft SQL Server 编写汉字转拼音函数
|
26天前
|
SQL 数据库
sqlserver建库建表建约束,删库删表删约束的示例总结
sqlserver建库建表建约束,删库删表删约束的示例总结
10 0
|
1月前
|
SQL 存储 数据库
数据安全无忧,SQL Server 2014数据库定时备份解密
数据安全无忧,SQL Server 2014数据库定时备份解密
|
1月前
|
SQL 网络协议 Windows
破解SQL Server迷局,彻底解决“管道的另一端无任何进程错误233”
破解SQL Server迷局,彻底解决“管道的另一端无任何进程错误233”