Sql server 如何在SQL Server上创建唯一的MD5哈希索引?
我想创建一个唯一的索引,用于检查表中的文本组合是否已经存在。在Sql server 如何在SQL Server上创建唯一的MD5哈希索引?,sql-server,md5,sql-server-2016,Sql Server,Md5,Sql Server 2016,我想创建一个唯一的索引,用于检查表中的文本组合是否已经存在。在PostgreSQL中,我通过一个简单的创建索引来实现这一点: CREATE UNIQUE INDEX table_unique ON cd.hdealerproductdata USING btree (md5((((svId::text || manufacturer::text) || manufacturerreference::text) || path::text) || treetype::text) C
PostgreSQL
中,我通过一个简单的创建索引来实现这一点:
CREATE UNIQUE INDEX table_unique
ON cd.hdealerproductdata USING btree
(md5((((svId::text || manufacturer::text) || manufacturerreference::text) || path::text) || treetype::text) COLLATE pg_catalog."default")
TABLESPACE pg_default;
如何在SQL Server(2016)中做到这一点?我尝试创建一个计算列(并向其中添加一个唯一的索引),如下所示(使用SSMS,table designer->Properties->computed column Specification):
ISNULL(HashBytes('MD5',CONVERT(VARCHAR(512),CONCAT(Manufacturer,ManufacturerReference)),'null')
但我有一个错误,说它不能被验证
编辑:我甚至可以将SHA-2与HashBytes一起使用:
Edit2.HashBytes
返回varbinary
类型,但我无法为计算列指定数据类型
之后:
'Document' table
- Unable to modify table.
Implicit conversion from data type varchar to varbinary is not allowed. Use the CONVERT function to run this query.
Edit3.:我最终为此创建了一个标量函数,并在插入和创建计算列时调用它(我在该列上持久化并创建了唯一索引)
并调用计算列:([dbo].[DocumentUniqueHash]([DocumentTreeId],[Manufacturer],[ManufacturerReference])
另外,插入存储过程是否如下所示:
CREATE PROCEDURE DocumentInsert
@DocumentTreeId bigint,
@Manufacturer nvarchar(255),
@ManufacturerReference nvarchar(255),
@NewId bigint OUTPUT
AS
BEGIN
SELECT @NewId = Id FROM Document (NOLOCK)
WHERE UniqueHash = [dbo].[DocumentUniqueHash](@DocumentTreeId, @Manufacturer, @ManufacturerReference)
IF @NewId IS NULL
BEGIN
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRANSACTION
SELECT @NewId = Id FROM Document (NOLOCK)
WHERE UniqueHash = [dbo].[DocumentUniqueHash](@DocumentTreeId, @Manufacturer, @ManufacturerReference)
IF @NewId IS NULL
BEGIN
INSERT INTO Document (DocumentTreeId, Manufacturer, ManufacturerReference)
VALUES (@DocumentTreeId, @Manufacturer, @ManufacturerReference)
SELECT @NewId = SCOPE_IDENTITY()
END
COMMIT TRANSACTION
END
SELECT @NewId
END
GO
是您选择的ISNULL
替换值让您绊倒
运行:
你得到了错误
Msg 257,第16级,第3状态,第4行
不允许从数据类型varchar隐式转换为varbinary。使用CONVERT函数运行此查询
但是运行以下查询:
declare @t table (Manufacturer varchar(512), ManufacturerReference varchar(512))
select ISNULL(HashBytes('MD5',CONVERT(VARCHAR(512),
CONCAT(Manufacturer,ManufacturerReference))), 0x) --not a string any more
from @t
它运行时没有错误这不太可能是偶然发生的,但既然已经证明了MD5碰撞,我怀疑它是否是评估唯一性的好候选。为什么您排除了对列本身应用唯一约束?@Damien\u不相信列是长varchar(nvarchar(512)
)。此外,我并不真的害怕md5碰撞意外发生(如果是故意的,那是另一个话题)。我可以使用sha1或更好,这并不重要。请求唯一散列没有意义。散列不是完全唯一的;它们是用于快速比较和扣扣的摘要。它们是故意的有损减少。如果你想要一个唯一的索引,你应该编写一些其他的东西,尽管基于你的用例,我会放弃唯一索引的想法。(也就是说,我很想听听你还能得到什么答案!)@CodeConfident有时候你只需要知道某些字符串在数据库中是否唯一。我认为使用散列(甚至是md5)效果很好。发生碰撞的可能性很小。绝对地做专栏。质疑它。但这不是唯一的限制。您试图告诉数据库强制执行一个不正确的数据不变量。
declare @t table (Manufacturer varchar(512), ManufacturerReference varchar(512))
select ISNULL(HashBytes('MD5',CONVERT(VARCHAR(512),
CONCAT(Manufacturer,ManufacturerReference))), 'null')
from @t
declare @t table (Manufacturer varchar(512), ManufacturerReference varchar(512))
select ISNULL(HashBytes('MD5',CONVERT(VARCHAR(512),
CONCAT(Manufacturer,ManufacturerReference))), 0x) --not a string any more
from @t