Nie wydaje się, że można to rozwiązać w czystym języku T-SQL, ponieważ ani CHARINDEXnie PATINDEXpozwala na użycie więcej niż 8000 bajtów w ciągu „do wyszukiwania” (tj. Maksymalnie 8000 VARCHARlub 4000 NVARCHARznaków). Można to zobaczyć w następujących testach:
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
Oba te zapytania zwracają następujący błąd:
Msg 8152, poziom 16, stan 10, wiersz xxxxx
Ciąg lub dane binarne zostałyby obcięte.
Zmniejszając 7000liczbę zapytań, aby 3999pozbyć się błędu. Wartość 4000w obu przypadkach również będzie błędna (z powodu dodatkowego N'Z'znaku na początku).
JEDNAK można to osiągnąć za pomocą SQLCLR. Utworzenie funkcji skalarnej, która akceptuje dwa parametry wejściowe typu, jest dość proste NVARCHAR(MAX).
Poniższy przykład ilustruje tę umiejętność przy użyciu darmowej wersji biblioteki SQL # SQLCLR (którą utworzyłem, ale String_Contains jest ponownie dostępny w bezpłatnej wersji :-).
USTAWIAĆ
-- 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;
TESTY
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
Należy pamiętać, że String_Contains korzysta z porównania wszystkiego ( wielkość liter, akcent, Kana i szerokość).
where st.text like '%MY_QUERY%CHARS%' ESCAPE '?'