2017-09-05 36 views
1

テーブル内のテキストの組み合わせが既に存在するかどうかを調べるユニークなインデックスを作成したいと思います。 PostgreSQLでは、私はシンプルなCREATE INDEXでこれをやった:SQL Serverで一意のMD5ハッシュインデックスを作成する方法は?

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; 

どのように私は(2016)SQL Serverでこれを行うことができますか?

ISNULL(HashBytes('MD5',CONVERT(VARCHAR(512),CONCAT(Manufacturer,ManufacturerReference))), 'null')しかし、私はそれを言ってエラーを得た:私は(SSMSを使用して、テーブルdesigner->プロパティ - >計算列仕様)このような計算列を(およびそれに一意のインデックスを追加)を作成してみました検証することはできません。 https://docs.microsoft.com/en-us/sql/t-sql/functions/hashbytes-transact-sql

EDIT2:HashBytes戻りvarbinaryタイプを私は計算列のデータ型を指定することはできません。

編集:私もHashBytesとSHA-2を使用することができます。

enter image description here

後:

'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)[email protected])[email protected])) 

    -- 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 
+0

MD5の衝突が* *実証されている、私はそれはだかどうかを疑問視したいので、それは偶然に起こることは稀ですが、一意性を評価するための良い候補者です。列自体に対して独自の制約を適用することを除外したのはなぜですか? –

+0

@Damien_The_Unbeliever列は長いvarcharsです( 'nvarchar(512)')。また、偶然に起こるmd5の衝突を本当に恐れているわけではありません(もしそれが意図的であれば、別の話題です)。私はsha1以上を使うことができました。それは本当に問題ではありません。 – appl3r

+0

ユニークなハッシュを要求するのは意味がありません。ハッシュは完全にユニークではありません。それらは、迅速な比較とバケッティングに使用されるダイジェストです。彼らは意図的に損失の削減です。ユニークなインデックスが必要な場合は、別のものを作成する必要がありますが、ユースケースに基づいて、ユニークなインデックスのアイデアをあきらめるだけです。 (それはあなたが他の答えを聞くことに興味があると言いました) – AjahnCharles

答えて

0

それはあなたをトリップだISNULL置換値のあなたの選択です。

ラン:

declare @t table (Manufacturer varchar(512), ManufacturerReference varchar(512)) 

select ISNULL(HashBytes('MD5',CONVERT(VARCHAR(512), 
     CONCAT(Manufacturer,ManufacturerReference))), 'null') 
from @t 

そして、あなたがメッセージ257、レベル16、状態3、VARBINARYへのデータ・タイプVARCHARから4行目

暗黙的な変換が許可されていないエラーに

を取得。この問合せを実行するには、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 

をそして、それはエラーなしで実行

+0

'ISNULL 'を使わなくても動作します。ありがとう。 – appl3r

関連する問題