Tampaknya ini tidak dapat diselesaikan dalam T-SQL murni karena tidak ada CHARINDEX
atau tidak PATINDEX
memungkinkan untuk menggunakan lebih dari 8000 byte dalam string "untuk mencari" (yaitu maks 8000 VARCHAR
atau 4000 NVARCHAR
karakter). Ini bisa dilihat pada tes berikut:
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
Kedua kueri tersebut menghasilkan kesalahan berikut:
Msg 8152, Level 16, State 10, Line xxxxx
String atau data biner akan terpotong.
Dan, mengurangi 7000
salah satu dari kueri tersebut untuk 3999
menghilangkan kesalahan. Nilai 4000
dalam kedua kasus juga akan kesalahan (karena N'Z'
karakter tambahan di awal).
NAMUN, ini bisa dicapai dengan menggunakan SQLCLR. Cukup mudah untuk membuat fungsi skalar yang menerima dua parameter input tipe NVARCHAR(MAX)
.
Contoh berikut menggambarkan kemampuan ini menggunakan versi gratis dari perpustakaan SQL # SQLCLR (yang saya buat, tetapi String_Contains lagi tersedia di versi gratis :-).
The String_Contains skalar UDF saat ini memiliki @SearchValue
param masukan sebagai NVARCHAR(4000)
bukan NVARCHAR(MAX)
(saya tidak harus berpikir orang akan mencari untuk string lebih dari 4000 karakter ;-) tapi itu sangat mudah untuk perubahan dengan membuat mengikuti perubahan satu kali (setelah SQL # telah diinstal, tentu saja):
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
MEMPERSIAPKAN
-- 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;
UJI
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
Harap diingat bahwa String_Contains menggunakan perbandingan (huruf, aksen, Kana, dan lebar) yang semuanya sensitif.
where st.text like '%MY_QUERY%CHARS%' ESCAPE '?'