如何在 SQL 服务器上创建唯一的 MD5 哈希索引?
How to create unique MD5 hash index on SQL Server?
我想创建一个唯一索引,用于检查我的 table 中的文本组合是否已经存在。在 PostgreSQL
中,我用一个简单的 CREATE INDEX
:
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 服务器 (2016) 中执行此操作?我尝试像这样创建一个计算列(并向其添加唯一索引)(使用 SSMS,table designer->Properties->Computed Column Specification):
ISNULL(HashBytes('MD5',CONVERT(VARCHAR(512),CONCAT(Manufacturer,ManufacturerReference))), 'null')
但我收到一条错误消息,提示无法验证。
编辑:我什至可以将 SHA-2 与 HashBytes
一起使用:https://docs.microsoft.com/en-us/sql/t-sql/functions/hashbytes-transact-sql
Edit2.: HashBytes
returns 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.: 我最终为此创建了一个标量函数,并在插入和创建计算列时调用它(我坚持并在其上创建了一个唯一索引)。
CREATE FUNCTION [dbo].[DocumentUniqueHash]
(
@DocumentTreeId bigint,
@Manufacturer nvarchar(255),
@ManufacturerReference nvarchar(255)
)
RETURNS varbinary(20)
WITH SCHEMABINDING
AS
BEGIN
-- Declare the return variable here
DECLARE @Result varbinary(20)
SELECT @Result = (hashbytes('SHA1',(CONVERT([nvarchar](max),@DocumentTreeId)+@Manufacturer)+@ManufacturerReference))
-- Return the result of the function
RETURN @Result
END
并调用了计算列:([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
替换值让您感到困惑。
运行:
declare @t table (Manufacturer varchar(512), ManufacturerReference varchar(512))
select ISNULL(HashBytes('MD5',CONVERT(VARCHAR(512),
CONCAT(Manufacturer,ManufacturerReference))), 'null')
from @t
你得到了错误
Msg 257, Level 16, State 3, Line 4
Implicit conversion from data type varchar to varbinary is not allowed. Use the CONVERT function to run this query.
但是 运行 这个查询:
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
它 运行 没有错误
我想创建一个唯一索引,用于检查我的 table 中的文本组合是否已经存在。在 PostgreSQL
中,我用一个简单的 CREATE INDEX
:
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 服务器 (2016) 中执行此操作?我尝试像这样创建一个计算列(并向其添加唯一索引)(使用 SSMS,table designer->Properties->Computed Column Specification):
ISNULL(HashBytes('MD5',CONVERT(VARCHAR(512),CONCAT(Manufacturer,ManufacturerReference))), 'null')
但我收到一条错误消息,提示无法验证。
编辑:我什至可以将 SHA-2 与 HashBytes
一起使用:https://docs.microsoft.com/en-us/sql/t-sql/functions/hashbytes-transact-sql
Edit2.: HashBytes
returns 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.: 我最终为此创建了一个标量函数,并在插入和创建计算列时调用它(我坚持并在其上创建了一个唯一索引)。
CREATE FUNCTION [dbo].[DocumentUniqueHash]
(
@DocumentTreeId bigint,
@Manufacturer nvarchar(255),
@ManufacturerReference nvarchar(255)
)
RETURNS varbinary(20)
WITH SCHEMABINDING
AS
BEGIN
-- Declare the return variable here
DECLARE @Result varbinary(20)
SELECT @Result = (hashbytes('SHA1',(CONVERT([nvarchar](max),@DocumentTreeId)+@Manufacturer)+@ManufacturerReference))
-- Return the result of the function
RETURN @Result
END
并调用了计算列:([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
替换值让您感到困惑。
运行:
declare @t table (Manufacturer varchar(512), ManufacturerReference varchar(512))
select ISNULL(HashBytes('MD5',CONVERT(VARCHAR(512),
CONCAT(Manufacturer,ManufacturerReference))), 'null')
from @t
你得到了错误
Msg 257, Level 16, State 3, Line 4
Implicit conversion from data type varchar to varbinary is not allowed. Use the CONVERT function to run this query.
但是 运行 这个查询:
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
它 运行 没有错误