Nie wydaje się, że można to rozwiązać w czystym języku T-SQL, ponieważ ani CHARINDEX
nie PATINDEX
pozwala na użycie więcej niż 8000 bajtów w ciągu „do wyszukiwania” (tj. Maksymalnie 8000 VARCHAR
lub 4000 NVARCHAR
znakó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 7000
liczbę zapytań, aby 3999
pozbyć się błędu. Wartość 4000
w 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 '?'