我想创建一个唯一的索引,检查我的表中的文本组合是否已经存在。在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 Server(2016)中执行此操作?我尝试创建一个计算列(并为其添加一个唯一索引),如下所示(使用SSMS,表设计器 - >属性 - >计算列规范):
ISNULL(HashBytes('MD5',CONVERT(VARCHAR(512),CONCAT(Manufacturer,ManufacturerReference))), 'null')
但我收到一条错误消息,说无法验证。
编辑:我甚至可以在HashBytes
使用SHA-2:https://docs.microsoft.com/en-us/sql/t-sql/functions/hashbytes-transact-sql
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。:我最终为此创建了一个Scalar函数,并在插入和创建计算列时调用它(我坚持并创建了一个唯一索引)。
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
并调用了Compute列:([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
答案 0 :(得分:1)
这是你选择的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
不允许从数据类型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
它运行没有错误