sql - 向超过 16 列的唯一行添加约束

标签 sql sql-server sql-server-2008 constraints

我有几个数据库表,我需要确保某些列在一起始终是唯一的。我目前使用这样的唯一约束:

ALTER TABLE [dbo].[MyTable] 
   ADD CONSTRAINT [AK_MyTable_Unique_Cols] 
   UNIQUE NONCLUSTERED ([Field_1] ASC, [Field_2] ASC,
                        [Field_3] ASC, [FkDeliveryId] ASC)
          WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, 
                SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, 
                ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
GO

表格看起来像这样。请注意,Sum 不是约束的一部分。

Field_1 | Field_2 | Field_3 | FkDeliveryId | Sum
Foo     | Foo     | Bar     | 1            | 100
Foo     | Bar     | Bar     | 1            | 900
Bar     | Foo     | Foo     | 1            | 400
Bar     | Foo     | Bar     | 2            | 800 // Not unique 
Foo     | Foo     | Bar     | 2            | 600
Bar     | Foo     | Bar     | 2            | 300 // Not unique

但问题是这些表是通过 C# 动态创建的,有些表的列数会超过 16 列。因此,当我尝试在具有 52 列的表上创建约束时,我收到此错误:

The index '' on table 'dbo.MyTable' has 52 columns in the key list. The maximum limit for index key column list is 16. Could not create constraint or index. See previous errors.

所以现在我正在寻找另一个解决方案。我的 SQL 知识仅限于查询数据库,而不是约束,所以请耐心等待。 :)

我的问题是:如何确保表中没有重复的行(基于选定的列数)?即使超过 16 列?

表可以有不同数量的列,并且列可以具有不同的数据类型。

我见过this question和哈希替代品一样。但当我有 50 多列和数百万行时,它还能工作吗?

请问 hash always be unique

根据评论更新:

这些表用于存储导入文件中的数据。我不知道文件的大小或它们有多少列。它是在计划作业中完成的,因此创建表的性能问题不是很重要。数据必须是持久的,但是实际上只需要约束来确保对于每个插入,没有行应该是重复的。理论上,列可能具有 varchar(max),这会导致哈希列变得非常大。

最佳答案

不,哈希值并不总是唯一的。发生哈希冲突。

这似乎是一个奇怪的要求。通常可以在表中的列子集上创建键。

绕过 16 列限制的通用解决方案是创建一个计算列,将所有列与数据中不太可能出现的某个分隔符连接起来,然后在其上创建唯一索引。这与您链接的问题所建议的基本相同。

但是索引键总体有 900 字节的限制。如果您需要支持任意列长度(包括可能超过此值的 varchar(max)),那么您无法使用声明性约束来做到这一点,并且需要一些过程代码。你能做的最好的事情就是创建一个散列和一个非唯一索引,然后让你的插入过程检查任何散列重复项,看看它们是否实际上是真正的重复项(可能发生在触发器中,以确保它始终被检查或 ETL 过程)本身 - 这可能会更有效)。

如果您在触发器中执行此操作,它将有助于向表中添加标识列。那么识别重复项的代码就是。

SELECT *
FROM Inserted I 
JOIN BaseTable B ON I.HashValue = B.HashValue AND I.Id<> B.Id 
/* check remaining columns to see if actual differences exist in null safe way  
   http://sqlblog.com/blogs/paul_white/archive/2011/06/22/undocumented-query-plans-equality-comparisons.aspx
  */
  AND EXISTS (SELECT B.Col1, B.Col2 
              INTERSECT
              SELECT I.Col1, I.Col2)

如果上面返回任何行,则您有违规并且可以回滚事务。

关于sql - 向超过 16 列的唯一行添加约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36908139/

相关文章:

c# - OrmLite插入0而不是自动递增主键

java - 连接到在线 SQL 数据库

sql - 清理数据源

sql-server-2008 - 由于硬盘崩溃而丢失的SQL查询可以恢复吗?

sql - T-SQL : can I use a variable as a database reference

SQL 触发器 - 如何获取更新的值?

sql-server - 在 SQL 中获取运行总计最大值的高性能方法

sql - Microsoft SQL 'not like' 与 <>

java - 当递归谓词使用绑定(bind)变量时,递归 CTE 不起作用

c# sql 返回没有时间的日期