Не здається, що це можна вирішити в чистому 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 '?'