SQL句で文字列をHash化する時にはデータ型に気を付けよう!

◆ Live配信スケジュール ◆
サイオステクノロジーでは、Microsoft MVPの武井による「わかりみの深いシリーズ」など、定期的なLive配信を行っています。
⇒ 詳細スケジュールはこちらから
⇒ 見逃してしまった方はYoutubeチャンネルをご覧ください
【5/21開催】Azure OpenAI ServiceによるRAG実装ガイドを公開しました
生成AIを活用したユースケースで最も一番熱いと言われているRAGの実装ガイドを公開しました。そのガイドの紹介をおこなうイベントです!!
https://tech-lab.connpass.com/event/315703/

こんにちは、サイオステクノロジーの佐藤 陽です。

今回はSQLで文字列をHash化するときに気を付けるポイントについてご紹介します。
基本的な事ですが、意外と気づかずハマってしまう人も多いかと思うので最後までご覧ください!

はじめに

今回はSQLServer(T-SQL)を題材にお話しします。

Databaseにデータを保存するとき、素のままではなくHASH化してから保存、というのはよくあるかと思います。
SQLServerには文字列をハッシュ化するHASHBYTESという関数が用意されています。

非常に便利な関数なんですが、これを使う際、一度ドはまりして解決に数日費やしてしまったことがあるので
同じような犠牲者を出さないよう、ここに書き留めたいと思います。

結論

早速ですが、結論です。

Hash化する元の文字列が同じ文字であっても、データ型が違う場合は異なるHash値が生成される場合があります!

検証

前提

SQLServerで文字列を扱う際、以下4つのデータ型が用意されています。

  • char:固定長, 全角2byte,半角1byte
  • nchar:固定長, 全角/半角ともに2byte
  • varchar:可変長,  全角2byte,半角1byte
  • nvarhcar:可変長, 全角/半角ともに2byte

試しに、同じ文字を4つの型に代入し、中身とbyte数を取得しました。

文字の中身は同じで、byte数が異なっていることが分かります。
これは半角文字のbyte数が異なっていることと、固定長or可変長によるためです。

Hash化

ではこの4つの文字列をHash化してみます。
今回はMD5のアルゴリズムで行いますが、他のアルゴリズムでも動作は同様です。

文字列としては同じですが、Hash化するとすべて異なる値となります。

考察は後にして、少し違うパターンのデータも入れてみます。
今回は空文字をHash化してみました。

空文字であったとしても、Hash値が異なってきていますね。
ただ、今回はvarcharとnvarharのHash値は同じとなりました。

最後に、文字数をデータ型のn値と同じにした場合で試してみます。(今回であれば10文字)

今回はvarcharとcharのHash値が等しく、nvarcharとncharのHash値が等しくなっていることが分かります。

以上の3パターンにおいて、Hash値とbyte数の結果から以下のことが分かります。

  • 同じ文字で、同じbyte数の場合は同じHash値が生成される
  • 同じ文字でも、byte数が異なっている場合は異なるHash値が生成される

まとめ

Hash化する際には、文字とbyte数が同じである必要があることが分かりました。
よくよく考えれば、Hash化は同じ文字ではなく同じデータの場合に、同じHash値が生成されるため、当たり前の挙動ですね。

ただ、当時はあまりデータ型を意識せず実装してしまっており、
「同じ文字なのにHash値が違う?!」という経験をしてしまいました。

文字を表すならなんでもいいや!ではなく
しっかり4つのデータ型を区別し、正しく把握したうえで実装する必要がありますね。

おまけ

先頭に紹介したMicrosoftのHASHBYTESのドキュメントを読むと

@input
ハッシュされるデータを含む変数を指定します。 @input は、varcharnvarchar、または varbinary です。

という記載があります。(2022/11現在)

そもそもchar,ncharがinputとして与えられることは想定されていないかもしれません。
今回はそれっぽく動作しましたが、注意して利用してください。

アバター画像
About 佐藤 陽 52 Articles
ロードバイクやトレランなど、走ることが好きなサーバーサイドエンジニア。組み込み系からWeb系へとジョブチェンジし、現在はAzureを使ったWebアプリの開発や、DevOpsの構築を行っています。
ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

役に立った 役に立たなかった

2人がこの投稿は役に立ったと言っています。


ご覧いただきありがとうございます。
ブログの最新情報はSNSでも発信しております。
ぜひTwitterのフォロー&Facebookページにいいねをお願い致します!



>> 雑誌等の執筆依頼を受付しております。
   ご希望の方はお気軽にお問い合わせください!

Be the first to comment

Leave a Reply

Your email address will not be published.


*


質問はこちら 閉じる