これを読むと LIKE文字の長さの制限 ここでは、LIKE句で〜4000文字を超えるテキストを送信できないようです。
特定のクエリのクエリプランキャッシュからクエリプランをフェッチしようとしています。
SELECT *
FROM sys.dm_exec_cached_plans AS cp
CROSS APPLY sys.dm_exec_query_plan(cp.plan_handle) AS qp
CROSS APPLY sys.dm_exec_sql_text(cp.plan_handle) AS st
where st.text like '%MY_QUERY_LONGER_THAN_4000_CHARS%' ESCAPE '?'
LIKE
内のクエリが4000文字よりも長い場合、クエリがキャッシュプランにある場合でも結果が0になります。 (私は少なくともerorrを期待していた)。
この問題を回避する方法または別の方法を使用する方法はありますか? > 10000
文字になるクエリがありますが、LIKE
では検索できないようです。
CHARINDEX
もPATINDEX
も「to search for」文字列で8000バイトを超えることができないため(つまり、最大8000 VARCHAR
または4000 NVARCHAR
文字)、これは純粋なT-SQLでは解決できないようです。これは、次のテストで確認できます。
_SELECT 1 WHERE CHARINDEX(N'Z' + REPLICATE(CONVERT(NVARCHAR(MAX), N'a'), 7000),
N'Z' + REPLICATE(CONVERT(NVARCHAR(MAX), N'a'), 6000)) > 0
SELECT 1 WHERE PATINDEX(N'Z' + REPLICATE(CONVERT(NVARCHAR(MAX), N'a'), 7000),
N'Z' + REPLICATE(CONVERT(NVARCHAR(MAX), N'a'), 6000)) > 0
_
これらのクエリはどちらも次のエラーを返します。
メッセージ8152、レベル16、状態10、行xxxxx
文字列型やバイナリは省略されます。
また、これらのクエリのいずれかで_7000
_を_3999
_に減らすと、エラーが解消されます。どちらの場合も_4000
_の値もエラーになります(先頭に余分な_N'Z'
_文字があるため)。
ただし、これはSQLCLRを使用して実行できます。タイプNVARCHAR(MAX)
の2つの入力パラメーターを受け入れるスカラー関数を作成するのはかなり簡単です。
次の例は、無料バージョンの SQL# SQLCLRライブラリを使用してこの機能を示しています(私が作成したライブラリですが、String_Containsが再び無料版で利用可能:-)。
[〜#〜]セットアップ[〜#〜]
_-- DROP TABLE #ContainsData;
CREATE TABLE #ContainsData
(
ContainsDataID INT NOT NULL IDENTITY(1, 1) PRIMARY KEY,
Col1 NVARCHAR(MAX) NOT NULL
);
INSERT INTO #ContainsData ([Col1])
VALUES (N'Q' + REPLICATE(CONVERT(NVARCHAR(MAX), N'a'), 15000)),
(N'W' + REPLICATE(CONVERT(NVARCHAR(MAX), N'a'), 20000)),
(N'Z' + REPLICATE(CONVERT(NVARCHAR(MAX), N'a'), 70000));
-- verify the lengths being over 8000
SELECT tmp.[ContainsDataID], tmp.[Col1], DATALENGTH(tmp.[Col1])
FROM #ContainsData tmp;
_
[〜#〜]テスト[〜#〜]
_SELECT tmp.[ContainsDataID], tmp.[Col1], DATALENGTH(tmp.[Col1])
FROM #ContainsData tmp
WHERE SQL#.String_Contains(tmp.[Col1], REPLICATE(CONVERT(NVARCHAR(MAX), N'a'), 15100)) = 1;
-- IDs returned: 2 and 3
SELECT tmp.[ContainsDataID], tmp.[Col1], DATALENGTH(tmp.[Col1])
FROM #ContainsData tmp
WHERE SQL#.String_Contains(tmp.[Col1], REPLICATE(CONVERT(NVARCHAR(MAX), N'a'), 26100)) = 1;
-- IDs returned: 3
_
String_Containsはすべてを区別する(大文字、小文字、アクセント、かな、幅)比較を使用していることに注意してください。
別のアプローチも求めたため、特定のプランを見つける別の方法は、次のようにクエリを変更して、そのplan_hash
を検索することです。
SELECT *
FROM sys.dm_exec_cached_plans AS cp
INNER JOIN sys.dm_exec_query_stats qs
ON cp.plan_handle = qs.plan_handle
CROSS APPLY sys.dm_exec_query_plan(cp.plan_handle) AS qp
CROSS APPLY sys.dm_exec_sql_text(cp.plan_handle) AS st
WHERE qs.query_hash = 0xE4026347B5F49802
検索するQueryHash
値を取得する最も簡単な方法は、問題のクエリをクエリウィンドウに貼り付けてから、推定実行プランを表示することです。 XML出力を読み、QueryHash
要素でStmtSimple
属性を探します。これにより、必要なものが得られます。 QueryHash値を上記のクエリにプラグインすると、期待どおりの結果が得られるはずです。
以下は、QueryHash
の値をすばやく取得する方法を示すスクリーンショットです。
推定実行計画を表示
実行プランXMを表示...
QueryHash値の検索
探しているクエリが推定実行プランを表示しているクエリと異なる場合、このトリックは機能しませんが、これはCLRルーチンに付属しているすべてのニュアンスよりも速く、それらを正しく機能させることができます。
クエリテキストにアクセスできる場合(変更できることを意味します)、興味のあるユーザーに一意のコメントを追加できます。
select /* myUniqueQuery123 */ whatever from somewhere ...
次に、クエリテキスト全体ではなく、プランキャッシュでmyUniqueQuery123
を検索します。
... where st.text like '%myUniqueQuery123%'
PS。未検証