Dan*_*inu 13 sql-server t-sql like sql-server-2016
通过在此处阅读此LIKE 字符长度限制,看起来我无法在 LIKE 子句中发送超过 ~4000 个字符的文本。
我正在尝试从特定查询的查询计划缓存中获取查询计划。
SELECT *
FROM sys.dm_exec_cached_plans AS cp
CROSS APPLY sys.dm_exec_query_plan(cp.plan_handle) AS qp
CROSS APPLY sys.dm_exec_sql_text(cp.plan_handle) AS st
where st.text like '%MY_QUERY_LONGER_THAN_4000_CHARS%' ESCAPE '?'
Run Code Online (Sandbox Code Playgroud)
如果里面的查询LIKE超过 4000 个字符,那么即使我的查询在缓存计划中,我也会得到 0 个结果。(我期待至少有一个错误)。
有没有办法解决这个问题或采取不同的方式?我有可能是 >10000字符长的查询,看起来我无法通过LIKE.
这似乎不能在纯 T-SQL 中解决,因为既不允许CHARINDEX也PATINDEX不允许在“搜索”字符串中使用超过 8000 个字节(即最多 8000VARCHAR或 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
Run Code Online (Sandbox Code Playgroud)
这两个查询都返回以下错误:
消息 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;
Run Code Online (Sandbox Code Playgroud)
测试
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
Run Code Online (Sandbox Code Playgroud)
请记住,String_Contains使用对所有内容敏感(大小写、重音、假名和宽度)的比较。