我有一个表,该表当前在一列中有重复的值。
我无法删除这些错误的重复项,但我想防止添加其他非唯一值。
我可以创建一个UNIQUE
不检查现有合规性的文件吗?
我曾尝试使用NOCHECK
但不成功。
在这种情况下,我有一个将许可信息与“CompanyName”联系起来的表
编辑:具有相同“公司名称”的多行是错误数据,但我们目前无法删除或更新这些重复项。一种方法是让INSERT
s 使用一个存储过程,该过程会因重复而失败......如果可以让 SQL 自己检查唯一性,那将是可取的。
该数据按公司名称查询。对于少数现有的重复项,这将意味着返回并显示多行......虽然这是错误的,但在我们的用例中是可以接受的。目标是防止它在未来发生。在我看来,我必须在存储过程中执行此逻辑。
答案是“是”。您可以使用过滤索引来执行此操作(有关文档,请参见此处)。
例如,您可以这样做:
这将创建一个唯一索引,仅在新行上,而不是在旧行上。这种特定的公式将允许使用现有值进行重复。
如果您只有少数重复项,则可以执行以下操作:
是的,你可以这么做。
这是一个重复的表:
让我们忽略现有的,并确保不能添加新的重复项:
让我们测试一下这个解决方案:
过滤的唯一索引是一个绝妙的主意,但它有一个小缺点 - 无论您使用
WHERE identity_column > <current value>
条件还是WHERE identity_column NOT IN (<list of ids for duplicate values here>)
.使用第一种方法,您将来仍然可以插入重复数据,即现有(现在)数据的重复。例如,如果您现在有(甚至只有一行)带有的行
CompanyName = 'Software Inc.'
,则索引不会禁止再插入一行具有相同公司名称的行。如果您尝试两次,它只会禁止它。使用第二种方法有一个改进,上述方法不起作用(这很好)。但是,您仍然可以插入更多重复项或现有重复项。例如,如果您现在有(两行或多行)带有的行
CompanyName = 'DoubleData Co.'
,则索引不会禁止再插入一行具有相同公司名称的行。如果您尝试两次,它只会禁止它。(更新)如果对于每个重复的名称,您可以在排除列表之外保留一个 id,则可以更正此问题。如果像上面的示例一样,有 4 行具有重复的
CompanyName = DoubleData Co.
ID 和 ID4,6,8,9
,则排除列表应该只有 3 个这些 ID。第二种方法的另一个缺点是繁琐的条件(繁琐的程度首先取决于有多少重复项),因为 SQL-Server 似乎不支持过滤索引部分的
NOT IN
运算符。WHERE
请参阅SQL-Fiddle。WHERE (CompanyID NOT IN (3,7,4,6,8,9))
如果您有数百个重复名称,那么您将不得不有类似WHERE (CompanyID <> 3 AND CompanyID <> 7 AND CompanyID <> 4 AND CompanyID <> 6 AND CompanyID <> 8 AND CompanyID <> 9)
I'm not sure if there is anefficiency with this condition,而不是。另一种解决方案(类似于@Alex Kuznetsov 的)是添加另一列,用排名数字填充它并添加一个包含此列的唯一索引:
DEFAULT 1
然后,由于属性和唯一索引,插入具有重复名称的行将失败。这仍然不是 100% 万无一失(而亚历克斯是)。Rn
如果在语句中明确设置INSERT
或Rn
值被恶意更新 ,重复项仍然会溜进来。SQL-Fiddle-2
另一种选择是编写一个标量函数来检查表中是否已经存在值,然后从检查约束中调用该函数。
这将对性能造成可怕的影响。
我正在寻找相同的东西 - 创建一个不受信任的唯一索引,以便忽略现有的错误数据,但新记录不能与已经存在的任何内容重复。
在阅读此线程时,我想到一个更好的解决方案是编写一个触发器,该触发器将针对父表检查 [inserted] 是否存在重复项,如果这些表之间存在任何重复项,则 ROLLBACK TRAN。