原文地址:http://www.cnblogs.com/caspnet/archive/2011/02/23/1962638.html

解决问题是:在一个表里面,有一个允许为空的字段,空是可以重复的,但是不为空的值需要唯一。

表结构如下面代码创建

CREATE TABLE test_tb
(
TestId int not null identity(1,1) primary key,
Caption nvarchar(100) null
);
GO

解决方案1:

对于这个问题,大家的第一个想法可能是:在Caption这个字段上面加一个唯一键不就可以了吗?好,我们按着这个思路做下去,先创建唯一索引。

CREATE UNIQUE NONCLUSTERED INDEX un_test_tb
ON test_tb(Caption)
GO

索引创建好了,我们来测试下效果

INSERT INTO test_tb (Caption)
VALUES (null)
GO
INSERT INTO test_tb (Caption)
VALUES (null)
GO

运行之后我们会收到下面的错误信息:

消息 2601,级别 14,状态 1,第 1 行
不能在具有唯一索引 'un_test_tb' 的对象 'dbo.test_tb' 中插入重复键的行。
语句已终止。

所以该解决方案是不行的。

解决方案2:

添加约束,让SQL Server在插入数据的时候,先验证下已有数据中是否有现在要插入的这个值。由于这个约束不是简单的一个运算,因此我们先创建一个函数,然后再在约束中调用这个函数。

创建验证逻辑函数:


CREATE FUNCTION [dbo].[fn_CK_test_tb_Caption]()
RETURNS BIT
AS
BEGIN
IF(EXISTS(
SELECT 1
FROM test_tb AS a
WHERE (Caption IS NOT NULL) AND EXISTS
(SELECT 1 AS Expr1
FROM test_tb
WHERE (Caption IS NOT NULL) AND (Caption = a.Caption) AND (a.TestId <> TestId))
))
RETURN 0 RETURN 1
END
GO

在约束中引用函数:

ALTER TABLE test_tb
ADD CONSTRAINT CK_test_tb_Caption CHECK (dbo.fn_CK_test_tb_Caption() = 1)
GO
现在来测试下效果。先来测试NULL值

INSERT INTO test_tb (Caption)
VALUES (null)
GO
INSERT INTO test_tb (Caption)
VALUES (null)
GO
SELECT * FROM test_tb
GO

可以成功运行,而且也出了多行为NULL的情况。现在再来测试不为空的插入情况。


INSERT INTO test_tb (Caption)
VALUES (N'AAA')
GO
INSERT INTO test_tb (Caption)
VALUES (N'BBB')
GO
INSERT INTO test_tb (Caption)
VALUES (N'BBB')
GO
SELECT * FROM test_tb
GO

结果是在第三条语句的时候报错了,表中的Caption字段也有'AAA'和'BBB'了,这也正好是我们要的结果。

所以解决方案2是正确的。但是为了这么一个小小功能,就写这么长一段东西是不是太繁琐了呢?我们来看下面的解决方案。

解决方案3:(只适用于SQL Server 2008)

SQL Server 2008中有了一个优雅的解决方案,那就是筛选索引。筛选索引是一种经过优化的非聚集索引,尤其适用于涵盖从定义完善的数据子集中选择数据的查询。筛选索引使用筛选谓词对表中的部分行进行索引。有了筛选索引,我们只需要写一条语句就达到上面的效果。

CREATE UNIQUE NONCLUSTERED INDEX un_test_tb
ON test_tb(Caption)
WHERE Caption is not null
GO

再用上面的一些测试语句来测试的话,会发现完全是达到了我们的要求。

这个方案的唯一缺点就是该语句只有SQL Server 2008支持。。

[转载]SQL Server如何保证可空字段中非空值唯一的更多相关文章

  1. SQL SERVER将某一列字段中的某个值替换为其他的值 分类: MSSQL 2014-11-05 13:11 67人阅读 评论(0) 收藏

    SQL SERVER将某一列字段中的某个值替换为其他的值 UPDATE 表名 SET 列名 = REPLACE(列名 ,'贷','袋') SQL SERVER"函数 replace 的参数 ...

  2. sql server中NULL导入decimal字段时报错

    sql server中NULL导入decimal字段时报错 在导入CSV文件时,如果decimal字段为null值,导致文本文件入库时失败. 错误现象 构造例子 新建一张表,包含decimal字段. ...

  3. [转载]C#中使用ADO.NET连接SQL Server数据库,自动增长字段用作主键,处理事务时的基本方法

    问题描述: 假设在数据库中存在以下两张数据表: User表,存放用户的基本信息,基本结构如下所示:   类型 说明 ID_User int 自动增长字段,用作该表的主键 UserName varcha ...

  4. 转载 SQL Server中索引管理之六大铁律

    转载原地址 http://jingyan.baidu.com/article/48a42057c03bd7a924250429.html 索引是以表列为基础的数据库对象.索引中保存着表中排序的索引列, ...

  5. 转载——SQL Server数据库性能优化之SQL语句篇

    转载自:http://www.blogjava.net/allen-zhe/archive/2010/07/23/326927.html 1. 按需索取字段,跟“SELECT *”说拜拜 字段的提取一 ...

  6. [转载]SQL Server中的事务与锁

    了解事务和锁 事务:保持逻辑数据一致性与可恢复性,必不可少的利器. 锁:多用户访问同一数据库资源时,对访问的先后次序权限管理的一种机制,没有他事务或许将会一塌糊涂,不能保证数据的安全正确读写. 死锁: ...

  7. 转载--SQL Server 2005的XQuery介绍

    原文地址: http://bbs.51cto.com/thread-458009-1-1.html   引用: 摘要 本文介绍了SQL Server 2005能够支持的XQuery的各方面特性如FLW ...

  8. SQL Server进阶(二)字段类型

    概述 系统数据类型详情 SqlDbType namespace System.Data { // // 摘要: // 指定要用于 System.Data.SqlClient.SqlParameter ...

  9. 将文件导入到SQL server数据库表中的字段中

    一.在要执行的sql server数据库a中执行如下脚本,创建存储过程sp_textcopy /* 将二进制文件导入.导出到数据库相应字段列中 */ CREATE PROCEDURE sp_textc ...

随机推荐

  1. NetBean常用快捷键(MAC中)

    shift+cmd+i:导入包 shift+alt+上:复制当前行,鼠标留在上一行   shift+alt+下:复制当前行,鼠标留在下一行 shift+ctrl+上:将选中行向上移动    shift ...

  2. python 中的metaclass和baseclasses

    提前说明: class object  指VM中的class 对象,因为python一切对象,class在VM也是一个对象,需要区分class对象和 class实例对象. class instance ...

  3. 全球IP分布表

    24.192.0.0 24.195.255.255 亚洲 61.0.0.0 61.255.255.255 亚洲 61.8.0.0 61.8.31.255 澳大利亚 61.128.0.0 61.143. ...

  4. ES6 笔记

    1.箭头函数 箭头函数里的this会引用 定义 箭头函数时,外部作用域 的 this .箭头函数只是 引用 外部作用域的 this ,本身不存在 this.同时因为没有 this ,所以 无法用new ...

  5. Object-C

    #import <Foundation/Foundation.h> #pragma mark 狗类的声明 @interface Dog:NSObject { @public NSStrin ...

  6. Attribute

    Attribute介绍 咱们来说Attribute,他是一个类,所以自定义的Attribute都是继承自System.Attribute,一般命名的时候都是以Attribute结尾.在使用的时候我们可 ...

  7. The communication of Linux Server and Localtion

    当用Secure CRT远程登录服务器时,若建立本地与服务器间文件自由传输的机制,我们就可以实现远程办公.具体方法如下: 1. 确定远程服务器的IP.可以通过Secure CRT进行远程登录. 2.在 ...

  8. 安装升级npm依赖

    npm-check 能够自动检索npm包版本,并且提供交互操作界面: 有以下功能: 1.告诉你那些依赖已经过时: 2.在你决定升级时,给你提供依赖包的文档: 3.提示某个依赖没有被你使用: 4.支持全 ...

  9. MySql的常用命令

    Ubuntu下的安装 打开"终端窗口",输入sudo apt-get update-->回车-->"输入root用户的密码"-->回车 输入s ...

  10. MyBatis 入门(一)

    MyBatis mybatis和hibernate都属于orm(对象与关系映射) 框架 mybatis的优点: 1.sql-mapping :操作更自由,可控性高,执行效率更高 2.轻量,学习更容易 ...