84

今朝少し奇妙なことに出くわしたので、コメントのために提出しようと思いました。

SQL 2008 に対して実行すると、次の SQL クエリが「等しい」と出力される理由を誰か説明できますか。データベースの互換性レベルは 100 に設定されています。

if '' = ' '
    print 'equal'
else
    print 'not equal'

これは 0 を返します。

select (LEN(' '))

スペースを自動トリミングしているようです。これが以前のバージョンの SQL Server に当てはまったかどうかはわかりません。また、テストする場所さえありません。

本番クエリが間違った結果を返すため、これに遭遇しました。この動作はどこにも文書化されていません。

誰もこれに関する情報を持っていますか?

4

8 に答える 8

92

varcharsと平等はTSQLでは厄介です。LEN関数は言う:

末尾の空白を除いて、指定された文字列式のバイト数ではなく文字数を返します。

DATALENGTH問題のデータの真のbyteカウントを取得するには、を使用する必要があります。Unicodeデータがある場合、この状況で取得する値はテキストの長さと同じではないことに注意してください。

print(DATALENGTH(' ')) --1
print(LEN(' '))        --0

式の同等性に関しては、2つの文字列が次のように同等性について比較されます。

  • 短い文字列を取得
  • 長さが長いストリングの長さと等しくなるまでブランクでパッドします
  • 2つを比較する

予期しない結果を引き起こしているのは中間のステップです。そのステップの後、空白と空白を効果的に比較しているため、それらは等しいように見えます。

LIKE=一致させようとしたパターンに対して空白のパディングを実行しないため、「空白」の状況よりも適切に動作します。

if '' = ' '
print 'eq'
else
print 'ne'

しばらくの間与えるでしょうeq

if '' LIKE ' '
print 'eq'
else
print 'ne'

あげるne

ただし、注意がLIKE必要です。対称ではありません。末尾の空白はパターン(RHS)で重要として扱われますが、一致式(LHS)では扱われません。以下はここから取られています:

declare @Space nvarchar(10)
declare @Space2 nvarchar(10)

set @Space = ''
set @Space2 = ' '

if @Space like @Space2
print '@Space Like @Space2'
else
print '@Space Not Like @Space2'

if @Space2 like @Space
print '@Space2 Like @Space'
else
print '@Space2 Not Like @Space'

@Space Not Like @Space2
@Space2 Like @Space
于 2009-09-09T14:14:21.460 に答える
9

この動作を説明し、その理由を説明しているこのブログ記事を見つけました。

SQL 標準では、文字列の比較では、短い文字列にスペース文字を効果的に埋め込む必要があります。 これは、N'' = N' ' (空の文字列は 1 つ以上の空白文字の文字列に等しい) という驚くべき結果につながり、より一般的には、末尾の空白だけが異なる場合、任意の文字列は別の文字列に等しくなります。これは、状況によっては問題になる可能性があります。

詳細については、MSKB316626も参照してください。

于 2009-09-09T15:03:21.603 に答える
5

少し前に同じような質問がありましたが、ここで同様の問題を調べました

の代わりにLEN(' ')、-を使用DATALENGTH(' ')して正しい値を取得します。

LIKE解決策は、そこにある私の答えで説明されているように条項を使用すること、および/またはWHERE条項に2番目の条件を含めてチェックするDATALENGTHことでした。

その質問とそこにあるリンクを読んでください。

于 2009-09-09T14:12:25.623 に答える
3

値をリテラル スペースと比較するには、LIKE ステートメントの代わりにこの手法を使用することもできます。

IF ASCII('') = 32 PRINT 'equal' ELSE PRINT 'not equal'
于 2011-02-24T20:03:11.973 に答える
0

別の方法は、スペースが価値のある状態に戻すことです。例: スペースを _ などの文字に置き換えます。

if REPLACE('hello',' ','_') = REPLACE('hello ',' ','_')
    print 'equal'
else
    print 'not equal'

戻り値: 等しくない

理想的ではなく、おそらく遅いですが、すぐに必要な場合の別の迅速な方法です。

于 2019-04-12T03:09:19.627 に答える
0

SQL Server でフィールド char/varchar を使用して select でレコードを区別する方法: 例:

declare @mayvar as varchar(10)

set @mayvar = 'data '

select mykey, myfield from mytable where myfield = @mayvar

期待される

マイキー (int) | マイフィールド (varchar10)

1 | 'データ '

得られた

マイキー | マイフィールド

1 | 'データ' 2 | 'データ '

select mykey, myfield from mytable where myfield = 'data'(最後の空白なしで)書いても 同じ結果が得られます。

どのように解決しましたか?このモードでは:

select mykey, myfield
from mytable
where myfield = @mayvar 
and DATALENGTH(isnull(myfield,'')) = DATALENGTH(@mayvar)

myfield にインデックスがある場合は、それぞれの場合に使用されます。

お役に立てば幸いです。

于 2015-04-14T15:45:59.903 に答える