问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

数据库唯一字段的问题

发布网友 发布时间:2022-08-02 20:10

我来回答

5个回答

热心网友 时间:2024-11-03 19:26

SQL Server如何保证可空字段中非空值唯一
今天同学向我提了一个问题,我觉得蛮有意思,现记录下来大家探讨下。
问题是:在一个表里面,有一个允许为空的字段,空是可以重复的,但是不为空的值需要唯一。

表结构如下面代码创建
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的解决方案,望不胜赐教。

热心网友 时间:2024-11-03 19:27

先用“姓名”查询,若返回结果集资料笔数大於0,则update,用第二次的数据按“姓名”更新“籍贯”;若返回笔数等於0,则insert
你的数据库是啥?Oracle的话可以用 merger into

热心网友 时间:2024-11-03 19:27

做程序不仅要有编程思想还要结合实际呀!你也不想想名字能做主键吗?!重名的可能性是很大的,在设计数据库的时候一般将名字作为主键,不指定其为唯一的;建议你设置一个编号字段,来唯一标识你的用户。

热心网友 时间:2024-11-03 19:28

那样你就不能把你的名字的字段设置成为主键,只要不设置主键就可以了,至于说想让数据库判断哪个更优越以我的程度我认为没法做到

热心网友 时间:2024-11-03 19:28

我觉得用SQL来约束比用程序写死要好点吧
在建立表格的时候就对该字段添加约束
create table AAAA (
name varchar2(8) NOT NULL UNIQUE,
add varchar2(20)
)
这样也可行的,试试看
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
为什么在你眼里,我连一句对不起都值不得 怎么回复? 我的主动在你眼里很廉价是什么意思 ...宫》金枝与四阿哥的对话 后面几句是什么?在那一集里的 国际经济与贸易的本科生需要考什么证? 关于网络诈骗的处罚方式是什么 惊艳!宁夏卫视倾情打造,首屈一指的财经直播频道 财经发展产物 如何做一本与众不同的财经期刊 财经类期刊杂志的运营策划 财富经济杂志栏目介绍 为什么压力低于蒸气压是全部蒸发 量10000枚一元硬币一共有多少厘米? ...枚硬币堆成一堆高度约是2分米,10000枚硬币堆成一堆高度约是( )毫 ... 已经激活的手机能退货吗 新手机激活后可以退货吗 老干妈鸡汤米线的做法,老干妈鸡汤米线怎么做好吃 鸡汤米线怎么做好吃 苹果手机设置里面怎么交罚款 可可果变成丝滑的巧克力怎样做? 猫咪放在后备箱里会不会闷死 猫放在后备箱会不会闷死 猫放后备箱会不会闷死 猫咪可以放后备箱多久 猫放轿车后备箱会闷死吗? 猫咪放后备箱会闷气吗 猫咪可以放在后备箱吗 小猫可以放在后备箱吗 青椒好不好吃? 青椒好吃么? 每天辛苦工作,为什么我升不了职 为什么努力却得不到升职机会?问题出在哪里? 在工作中做了正确的事,为何自己还是不能升职? Oracle数据库!!!触发器!!!不是可以replace掉另一个触发器么??为什么... 上课经常走神,听课不专心怎么办 总在想着事情 上课不能专心听课 我为什么上课不能专心听讲!!! 怎样才能防止上课不专心听讲呢? 小学生上课不专心听讲怎么办 人本主义疗法的过程 人本主义的常见疗法 人本主义方法是不是指示性的心理治疗方法 人本主义疗法的技术 不固定角色属于什么疗法 请问mysql命令行如何创建触发器啊,我试了几次都是错误的,触发器是这... 手机银行交违章罚款为什么记录还未处理 触发器和硬件有关吗 SQL数据库应用 自考 求高手真心帮忙阿!!! 很着急!! sql中如何建立一个触发器,使出入和删除某条记录时,系统能自动进行相关... 求SQL插入触发器语句 oracle怎么用触发器删除依赖关系的表的数据 oracle 触发器删除约束条件的数据把所有数据都删除了 春季怎么减肥最快 首选6种消脂食物