2

単一のクエリを使用して、SQL でおそらく数千行のテキストを連結しようとしています。現在のクエリは次のようになります。

DECLARE @concatText NVARCHAR(MAX) 
SET @concatText = ''

UPDATE TOP (SELECT MAX(PageNumber) + 1 FROM #OrderedPages) [#OrderedPages] 
SET @concatText = @concatText + [ColumnText] + '
'
WHERE (RTRIM(LTRIM([ColumnText])) != '')

これは、機能的な観点からは完全に正常に機能しています。唯一の問題は、ColumnText の長さが数キロバイトになる場合があることです。その結果、これらの行が数千になると、tempDB がいっぱいになります。

私たちが思いついた一番の理由は、@concatText に対してこれらの更新を行っているときに、SQL が暗黙のトランザクションを使用しているため、文字列が事実上不変になっているということです。

この問題を解決する良い方法を見つけようとしていますが、これまでのところ 2 つの解決策があります。1) .NET で連結を行います。これは問題のないオプションですが、大量のデータがネットワークを介して戻ってくる可能性があります。

2) .NET の String.Join メソッドと同様の方法で動作する .WRITE を使用します。BoL はこのレベルの SQL シェナニガンをカバーしていないため、これの構文を理解できません。

これは私に疑問を投げかけます: .WRITE は動作しますか? もしそうなら、構文は何ですか?そうでない場合、データを .NET に送信せずにこれを行う他の方法はありますか? FOR XMLテキストに不正な XML 文字が含まれている可能性があるため、使用できません。

前もって感謝します。

4

4 に答える 4

2

@Martinのコメントで示唆されているように、CLR統合の使用を検討します。CLR集約関数は、単なるチケットである可能性があります。

于 2011-05-11T16:17:44.183 に答える
1

tempdbがいっぱいになるのは正確には何ですか? 不変性はなく@concatText = @concatText + [ColumnText]、@concatText変数は最悪の場合2GBのサイズになります(tempdbはそれよりもはるかに大きいと思いますが、それを増やしません)。クエリ プランがハロウィン保護用のスプールを作成し、そのスプールが原因のようです。

一般的な回答として、UPDATE ... SET @var = @var + ...for 連結の使用には正確性の問題があることが知られており、サポートされていません。より確実に機能する別の方法については、「 Transact-SQL での行の値の連結」で説明しています。

于 2011-05-11T18:33:55.777 に答える
0

同意..CLRユーザー定義関数は、皆さんが行っていることに対する最良のアプローチです。実際にテキスト値をオブジェクトに読み込んでから (CLR 内で) それらをすべて結合し、関数で NVARCHAR(MAX) の結果を吐き出すことができます。これを行う方法の詳細が必要な場合は、お知らせください。

于 2011-05-12T01:28:46.613 に答える
0

まず、投稿から、一時テーブルが必要かどうか、またはその理由が明確ではありません。連結は、クエリ内でインラインで実行できます。tempdb をいっぱいにしているクエリについて詳しく教えていただければ、それを書き直すお手伝いができるかもしれません。第 2 に、言及されていないオプションは、T-SQL の外部で文字列操作を完全に行うことです。つまり、生データの中間層クエリで操作を行い、それをデータベースにプッシュします。最後に、結果がエスケープとエンティティを適切に処理するように Xml を使用できます。繰り返しますが、私たちはあなたが何をどのように達成しようとしているのかについてもっと知る必要があります.

于 2011-05-11T16:52:21.030 に答える