首页 > 解决方案 > 带有 STUFF 和 FOR XML 路径的 T-SQL 中 WHERE 子句中的动态 LIKE

问题描述

我要做的是在文本列中搜索LIKE值列表中的任何内容。

带有文本列的表非常大,所以我无法加入LIKE '%' + valuename + '%'(临时表的值列表不是很大)。

%我想我会尝试这样做,但我需要在动态WHERE子句中加上单引号。也许这是不可能的。

这是一个例子:

CREATE TABLE #SearchValues (valuename VARCHAR(20))

INSERT INTO #SearchValues
VALUES ('Red235'), ('Blue678'), ('2Purple'), ('63Cyan'),('99Black')

CREATE TABLE #TextTable (textfield VARCHAR(300))

INSERT INTO #TextTable
VALUES ('"Red235"'), ('blah and [99Black]'), ('something else'), ('n'),
       ('63Cyan'), ('other text'), ('nothing'), ('[2Purple]'), ('')

SELECT 
    -- this would be it except that it needs the single quotes around the %
    WhereClauseIWant = STUFF((SELECT ' OR valuename LIKE %' + valuename + '%'
                              FROM #SearchValues
                              FOR XML PATH('')), 1, 19, '') 

SELECT *
FROM #TextTable
WHERE textfield LIKE STUFF((SELECT ' OR valuename LIKE ' + '%' + valuename + '%'
                            FROM #SearchValues
                            FOR XML PATH('')), 1, 19, '')

标签: sqlsql-servertsql

解决方案


EXISTS理想情况下,您应该只在静态查询中使用谓词。

SELECT *
FROM #TextTable T
WHERE EXISTS (SELECT 1
    FROM #SearchValues s
    WHERE t.textfield LIKE '%' + s.valuename + '%'
);

如果您真的打算使用动态 SQL,那么您显然需要EXEC,并且需要安全地执行此操作。你也有一些错别字。

注意使用QUOTENAME安全注入,并.value防止 XML 实体化。

DECLARE @sql nvarchar(max) = N'
SELECT *
FROM #TextTable
WHERE 1=0
' + (
    SELECT '
OR textfield LIKE ' + QUOTENAME('%' + valuename + '%', '''')
    FROM #SearchValues
    FOR XML PATH(''), TYPE
).value('text()[1]','nvarchar(max)');

PRINT @sql;  -- for testing
EXEC sp_executesql @sql;

推荐阅读