Не здається, що це можна вирішити в чистому T-SQL, оскільки ні він CHARINDEXне PATINDEXдозволяє використовувати більше 8000 байт у рядку "для пошуку" (тобто максимум 8000 VARCHARабо 4000 NVARCHARсимволів). Це можна побачити в наступних тестах:
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
Обидва ці запити повертають таку помилку:
Msg 8152, рівень 16, стан 10, рядок xxxxx
Рядок або двійкові дані будуть усічені.
І, зменшуючи 7000будь-який із цих запитів, щоб 3999позбутися помилки. Значення 4000в обох випадках також буде помилковим (через додатковий N'Z'символ на початку).
ЗАРАЗ, це може бути здійснено за допомогою SQLCLR. Досить просто створити скалярну функцію, яка приймає два вхідні параметри типу NVARCHAR(MAX).
Наступний приклад ілюструє цю здатність за допомогою Безкоштовної версії бібліотеки 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 використовує порівнянне з урахуванням усе (регістр, акцент, Kana та ширина).
where st.text like '%MY_QUERY%CHARS%' ESCAPE '?'