【问题标题】:How can I enforce uniqueness on a NVARCHAR(MAX) column in SQL Server?如何在 SQL Server 中的 NVARCHAR(MAX) 列上强制唯一性?
【发布时间】:2011-07-22 16:57:14
【问题描述】:

我在 SQL Server 2008 R2 中有一个列是 NVARCHAR(MAX)。我想在该列上设置唯一索引,但唯一索引中包含的列的最大大小为 NVARCHAR(450) 或 900 字节。

如何在 NVARCHAR(MAX) 列上强制唯一性?

谢谢!

【问题讨论】:

  • 你实际上不能 - 见上文并投票结束。
  • @Yuck - 可能有超出内置约束的方法。问题是关于强制唯一性,不一定要在字段上添加约束。
  • 这可能会在其他地方被问到,但这是一个不同的问题:“为什么我不能对 nvarchar(max) 施加约束”我认为 Lucero 很好地回答了这个问题

标签: sql-server sql-server-2008-r2


【解决方案1】:
  1. 在某种散列(例如 CHECKSUM)上创建持久列。例如:Hash = MyStringHash as CHECKSUM(MyString)
  2. 在该列上创建非唯一索引
  3. 创建一个强制唯一性的触发器。需要索引来加快 EXISTS 子句中的搜索:

            WHERE   NOT EXISTS ( SELECT 1
                                 FROM   YourTable AS y
                                 WHERE  y.MyStringHash = CHECKSUM(Inserted.MyString)
                                        AND y.MyString = Inserted.MyString) ;
    

重要提示:您需要针对您的排序规则进行测试。如果您使用不区分大小写的排序规则,请确保触发器不会同时允许“MyTest”和“MYTEST”。

如果你追求一个唯一的索引并停在那里,你只是在创造一个等待发生的错误。

编辑:在不区分大小写的环境中,我已将 CHECKSUM 用于持久计算列,它速度快、不区分大小写且具有足够的选择性。

【讨论】:

  • Alex,我假设您的意思是在计算列中使用 CHECKSUM。感谢您的解决方案! :)
  • CHECKSUM 是一个非常糟糕的选择:发生冲突的几率很高。
【解决方案2】:

我和科里有同样的想法。假设与 SHA1 的冲突不太可能发生,您可以执行以下操作:

CREATE TABLE [dbo].[tblHash](
    [s] [nvarchar](MAX) NOT NULL,
    [h]  AS (hashbytes('SHA1',[s])) PERSISTED,
    CONSTRAINT [IX_tblHash] UNIQUE NONCLUSTERED (
        [h]
    )
)

【讨论】:

  • 行不通。 Hashbytes 限制为 8k 字节。您需要编写自己的哈希字节来处理超过 8k 字节,然后处理它很慢的事实。 msdn.microsoft.com/en-us/library/ms174415.aspx - “允许的输入值限制为 8000 字节。”
【解决方案3】:

您如何担心会出现重复的大字段?

一种方法是创建一个像LEFT(NvarCharMaxField, 200) 这样的计算字段,并在那个上放置一个唯一索引。除此之外,我认为没有办法,除非您添加触发器,否则将非常昂贵。

【讨论】:

  • 同意,nvarchar(max) 字段不应该需要唯一索引来开始。该字段中存储了什么,是否可以将其重构为可以索引的内容?
【解决方案4】:

您可以对 NVARCHAR(MAX) 字段使用某种哈希函数,并在哈希字段上创建一个唯一索引。

编辑:

正如 Yuck 所指出的,散列函数的工作方式确实存在发生冲突的可能性。如果您使用诸如 SHA1 之类的散列,则(可能但)极不可能发生冲突。

【讨论】:

  • 与任何哈希函数一样,您可能会发生冲突,因此这会产生误导。
  • @Yuck,像 SHA1 这样的加密哈希应该不太可能发生冲突。
  • 根据@Lucero 所说的,编辑您的答案,以便我删除反对票。
猜你喜欢
  • 2018-05-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-15
  • 2017-10-12
  • 2020-09-12
  • 1970-01-01
相关资源
最近更新 更多