Es scheint nicht möglich zu sein, dies in reinem T-SQL zu lösen, da weder CHARINDEX
nochPATINDEX
erlauben für die Verwendung von mehr als 8000 Bytes in der Zeichenfolge (dh max von 8000 „suchen“ VARCHAR
oder 4000 NVARCHAR
Zeichen). Dies zeigt sich in folgenden Tests:
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
Beide Abfragen geben den folgenden Fehler zurück:
Meldung 8152, Ebene 16, Status 10, Zeile xxxxx
oder Binärdaten werden abgeschnitten.
Reduzieren Sie den Wert 7000
in einer dieser Abfragen, 3999
um den Fehler zu beheben. Ein Wert von 4000
in beiden Fällen wird ebenfalls fehlerhaft (aufgrund des zusätzlichen N'Z'
Zeichens am Anfang).
Dies kann jedoch mit SQLCLR erreicht werden. Es ist ziemlich einfach, eine Skalarfunktion zu erstellen, die zwei Eingabeparameter vom Typ akzeptiert NVARCHAR(MAX)
.
Das folgende Beispiel veranschaulicht diese Möglichkeit mit der kostenlosen Version der SQL # SQLCLR-Bibliothek (die ich erstellt habe, aber String_Contains ist in der kostenlosen Version wieder verfügbar :-).
Die String_Contains skalare UDF hat zur Zeit den @SearchValue
Eingang param als NVARCHAR(4000)
statt NVARCHAR(MAX)
(ich muss nicht gedacht haben Menschen auf der Suche würde für Strings von über 4000 Zeichen ;-) , aber das ist sehr einfach zu ändern , indem Sie die folgende einmalige Änderung vorgenommen (nach SQL # wurde natürlich installiert):
GO
ALTER FUNCTION [SQL#].[String_Contains](@StringValue [NVARCHAR](MAX),
@SearchValue [NVARCHAR](MAX))
RETURNS [BIT]
WITH EXECUTE AS CALLER
AS EXTERNAL NAME [SQL#].[STRING].[Contains];
GO
INSTALLIEREN
-- 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;
TESTS
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
Beachten Sie, dass String_Contains einen allsensitiven Vergleich (Groß- / Kleinschreibung, Akzent, Kana und Breite) verwendet.
where st.text like '%MY_QUERY%CHARS%' ESCAPE '?'