【问题标题】:SQL Server Unique Index on (all) NON-NULL row values(所有)非空行值的 SQL Server 唯一索引
【发布时间】:2015-07-24 11:39:33
【问题描述】:

我有一张表格,用于推送相关数据。它有 6 个可以为空的列。根据一些逻辑,2 的组合总是非空的(第一个 + 最后 4 个中的一个和第二个 + 最后 4 个中的一个)。这样我就避免了使用 8 个不同的表来保存数据。

是否有任何 T-SQL (开始对 SQL Server 细节相当陌生) 快捷方式来在这 6 列上创建唯一键,以确保索引中提到的列之间的任何非空组合(1st - 6th) 是独一无二的,而没有真正具体的开始?

我可以为每个组合创建唯一索引,但我想知道是否有任何捷径可以保持懒惰并使用 (write) 1 个索引与其中 8 个索引。这显然不是一个很大的努力,但任何更短的东西都会更好......在代码中,大多数时候!

【问题讨论】:

  • 拥有空列只是为了避免创建正确的表是一个糟糕的设计,其中一个后果是您需要添加检查和约束以避免错误的值。而是创建一个适当的设计。如果您想一次从所有表中读取数据,请使用带有联合的视图
  • @PanagiotisKanavos 我知道这是糟糕的设计,但是 8 个表让 SqlServer 的生活更轻松,而 1 个表让我的生活更轻松。鉴于该表 99% 是只读的,而且不经常访问……对我来说更轻松的生活是当务之急。 ;)
  • 那你为什么会遇到麻烦?实际上,它们使服务器和程序员的事情都更糟。 SQL Server 有一些高级功能可以克服这些缺点,但最终你必须修复设计
  • @PanagiotisKanavos 不得不进行一些更改并更新 8 个表......并不是那么有趣。所以我把它们结合起来。我最初构建了 8 ......但是更新 8 并不好玩。尤其是 DB + Code 方面。 :)
  • 根据您的描述,您似乎只需要 两个 表,每个表有 4 个可空列。第一/第二列不能为空,它们只会分别出现在第一、第二表中。如果你解释了你想要做什么,你可以进一步简化它。例如,如果您使用可为空的列来强制从标志或位域中选择单个值,则可以使用查找表并仅创建单个查找列

标签: sql-server tsql


【解决方案1】:
  1. 进行检查约束以确保仅设置前两个中的一个和后四个中的一个。
  2. 创建一个计算列coalesce(c1, c2) 和一个列coalesce(c3, c4, c5, c6)
  3. 创建唯一索引(computed1, computed2)

我希望我做对了。也许你需要稍微改变一下。

【讨论】:

  • 这是个好主意。我已经有了CHECK。一个问题是值是指向哈希表的数字,因此它们可能会发生冲突。但是我可以用这些计算列编写一个解决方案只需要再添加 2 个 case 来保存第一个非空列的数字 (1/2) 和 (3/4/5/ 6) 对于第二个非空列。 -- 我可能错过了计算列...值得提出这个问题。谢谢!
【解决方案2】:

在类似的东西上创建一个计算列:

COALESCE(
   cast(1 as binary(1)) + cast(col1 as binary(4)) /* Choose appropriate length for the type of col1 */
  ,cast(2 as binary(1)) + cast(col2 as binary(4)) /* Choose appropriate length for the type of col2 */
)
+ COALESCE(
   cast(3 as binary(1)) + cast(col3 as binary(4)) /* Choose appropriate length for the type of col3 */
  ,cast(4 as binary(1)) + cast(col4 as binary(4)) /* Choose appropriate length for the type of col4 */
  ,cast(5 as binary(1)) + cast(col5 as binary(4)) /* Choose appropriate length for the type of col5 */
  ,cast(6 as binary(1)) + cast(col6 as binary(4)) /* Choose appropriate length for the type of col6 */
  )

您可能不需要每对中的第一个值 - 取决于 (17,null,1,null,null,null) 是否应该与 (null,17,null,null,1,null) 相同.

但无论如何,使用此计算列,您可以在其上放置唯一索引。 :)

您可以在两列中执行此操作,但您可以像这样在单个列中执行此操作。

【讨论】:

  • 过滤索引可以解决这个问题。不过,更好的数据库设计会好得多
  • 那么我认为你应该想出一个过滤索引来解决它......我认为索引需要跨越所有行,所以过滤索引不能解决它。
  • 我不会首先使用带有空值的单个表来“避免”创建多个表。完全避免了这个问题。从描述来看,四个可为空的列似乎只需要 2 个表。
  • 当然,但人们并不总是能够选择他们正在处理的数据库设计。
  • 如果您检查问题,OP 创建此问题以避免创建更多表
【解决方案3】:

我认为不存在,SQL-Server 中的索引是唯一的(在索引中的所有行上)或者它不是唯一的。

【解决方案4】:

只需在 6 列上创建唯一索引

【讨论】:

  • 空值呢? 6 列,在任何给定时间只有 2 列是非空的。
  • null 呢?如果两个不为空且唯一,则添加 4 个空,它仍然是唯一的。
猜你喜欢
  • 2014-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-08
  • 2011-01-16
  • 1970-01-01
  • 2014-08-18
相关资源
最近更新 更多