SQL Serverは、等しい比較ではなく、類似の比較ではないvarchar値の自動トリム


13

今日、SQL Serverでいくつかの興味深い動作(2005年と2012年に観測)に遭遇しました。

=NVARCHARフィールドを使用して比較を行うクエリは、文字列の末尾のスペースを無視しました(または比較前に値を自動トリミングしました)が、like演算子を使用した同じクエリはスペースを無視しませんでした。使用されている照合は、2012年にLatin1_General_CI_ASです。

このSQL Fiddleを検討してくださいhttp : //sqlfiddle.com/#!6/72262/4

like演算子は末尾のスペース文字列の結果を返さないが、演算子は返すことに注意してください=。どうしてこれなの?

ボーナスポイント:これをVARCHARフィールドに複製することはできません。スペースは両方のデータタイプで同じように処理されると考えていました。これは本当ですか?


文字列がトリミングされるというチェック制約を記述しようとしていました。私はそれをチェックすることです回避策たMyString+'x' = ltrim(rtrim(MyString))+'x'提案として、このブログに
default.kramer

回答:


15

私の最初の答えは、OFFに設定されたANSI_PADDINGフラグが動作の違いのせいかもしれないことを示唆しました。ただし、これは正しくありません。このフラグはストレージにのみ影響しますが、等価比較には影響しません。

この違いは、MicrosoftによるSQL標準の実装に起因しています。標準では、等価性をチェックする場合、等価演算子の左右両方の文字列を同じ長さになるようにパディングする必要があるとされています。これにより、次の結果が説明されます。

insert into test_padding (varchar_clmn, nvarchar_clmn) values ('space ', 'nspace ')
go
-- equality for varchar column
select count(*) from test_padding where varchar_clmn = 'space' -- returns 1
select count(*) from test_padding where varchar_clmn = 'space ' -- returns 1
select count(*) from test_padding where varchar_clmn = 'space    ' --returns 1
-- equality for nvarchar column
select count(*) from test_padding where nvarchar_clmn = 'nspace' -- returns 1
select count(*) from test_padding where nvarchar_clmn = 'nspace ' -- returns 1
select count(*) from test_padding where nvarchar_clmn = 'nspace    ' --returns 1

LIKE演算子は、オペランドを埋め込みません。列タイプ列タイプに対しても異なる動作をVARCHARNVARCHARます

-- likeness for varchar column
select count(*) from test_padding where varchar_clmn like 'space' -- returns 1
select count(*) from test_padding where varchar_clmn like 'space ' -- returns 1
select count(*) from test_padding where varchar_clmn like 'space    ' -- returns 0
-- likeness for nvarchar column
select count(*) from test_padding where nvarchar_clmn like 'nspace' -- returns 0
select count(*) from test_padding where nvarchar_clmn like 'nspace ' -- returns 1
select count(*) from test_padding where nvarchar_clmn like 'nspace    ' -- returns 0

ASCIIタイプのLIKE演算子の動作は、SQL Server固有です。Unicodeタイプの場合、ANSIに準拠しています。


4

SQLは、ほとんどのデータ処理言語がすべてのフィールド/変数に固定長を使用した時代に生まれました。余分なスペースを含むテキストフィールドの自動パディングもその図の一部でした。この動作に合わせて、元のSQL CHAR型は、末尾のスペースを無視するように「=」演算子に対して明示的に定義されています。(奇妙なことに気づいたら、テキストに追加された末尾のスペースが実際のビジネス上の意味を持つという説得力のあるケースを教えてください。)

それ以降、SQL CHAR型はあらゆる方向に進化してきましたが、特定のより新しいデータ型が、過去の前身からいくつかの特性を継承していることは考えられません。


「テキストに追加された末尾のスペースが実際のビジネス上の意味を持っている魅力的なケースを見せてください」-特定の生のコンソール出力や事前に安全でないXMLフラグメントなどの空白が重要なデータを保存します。
ダイ

1

LIKE(Transact-SQL)のドキュメントには、Microsoftが次のように書いています(私の強調)。

LIKEを使用したパターンマッチング

LIKEは、ASCIIパターンマッチングとUnicodeパターンマッチングをサポートしています。すべての引数...がASCII文字データ型の場合、ASCIIパターンマッチングが実行されます。引数のいずれかがUnicodeデータ型の場合、すべての引数はUnicodeに変換され、Unicodeパターンマッチングが実行されます。LIKEでUnicodeデータを使用する場合、末尾の空白は重要です。ただし、非Unicodeデータの場合、末尾の空白は重要ではありません。Unicode LIKEはISO標準と互換性があります。ASCII LIKEは、以前のバージョンのSQL Serverと互換性があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.