FC2ブログ
 

Technology へようこそ
ここは技術者の「経験」と「ノウハウ」のブログです


--年--月--日

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。


2010年05月07日

クエリ文字列結合の罠

SQLServer2005以降、nvarchar/varchar 型のサイズとして「max」が指定できるようになりました。
それまでは最大で4000文字(varcharは8000文字)という制限があり、ストアドプロシージャなどで長めの動的クエリを記述する場合、ひとつの変数にはクエリ文字列が収まりきらず、仕方なく複数のクエリ格納用変数を使って用意して、実行時に文字列結合、なんていう技を使っていたりしたものですが、「max」登場により、そういった見苦しいコードを書かなくて済むようになったかと思いきや、コトはそう単純な話ではなかったようです。

そう、たしかに格納先変数のサイズ制限自体は緩くなってはいるのですが、値をセットする際の「リテラル文字列自体の長さ」については従来通りの制限があるのです。
つまり、4000文字(あるいは8000文字)の文字列を一気に変数にセットできない、ということ。
ちなみにマイクロソフトはこの仕様について変更する気はなさげ

もちろん、従来通りリテラル文字列を分割して順次代入していく形にすれば回避はできますが、やはりどう考えても見苦しいうえに面倒臭い。
もう少しスマートに回避する方法はないかと思いきや、
文字列連結のリファレンスにこんな記述を発見。
文字列の連結の結果が8,000バイトを超える場合、結果は切り捨てられます。
ただし、連結する文字列の少なくとも一方が大きな値の型の場合、切り捨ては行われません。
というわけで、試してみたところ、下記「OK Case」のように、単純にmaxサイズの文字型変数を結合してやれば良いことが判明。
これならほとんど違和感なく記述できそうです、というより
これはもはやコーディング規約にしてしまったほうが良いかもしれない世界。
declare @sql nvarchar(max)

set @sql = ''
set @sql = N'start' + replicate(N'X', 4000) + N'end'
print 'NG Case: ' + str(len(@sql))

set @sql = ''
set @sql = @sql + N'start' + replicate(N'X', 4000) + N'end'
print 'OK Case: ' + str(len(@sql))

処理結果)
NG Case: 4000
OK Case: 4008

注意)
print文では4000文字(あるいは8000文字)を超える文字列は常に切り詰めて出力されます。
変数の内容を確認する際にはselect文等を利用しませう。

[ posted by ken ]

この記事に対するコメント


この記事に対するコメントの投稿














管理者にだけ表示を許可する



この記事に対するトラックバック
トラックバックURL
http://comfair2.blog24.fc2.com/tb.php/467-07ee7392
この記事にトラックバックする(FC2ブログユーザー)











上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。