另一个答案是使用CTE在进行搜索之前剥离HTML。
以下CTE提取可能满足搜索条件的行,并递归地剥离HTML。然后,查询使用CTE的结果来过滤仍包含HTML和不完全匹配搜索条件的行。
CTE并不像看起来那么复杂。大部分的调整是为了应对PATINDEX返回0的情况。
DECLARE @HTML TABLE (id INT IDENTITY, html VARCHAR(max))
INSERT INTO @HTML SELECT 'This is a <span style="font-weight: bold; ">nice</span> question';
INSERT INTO @HTML SELECT 'The cat sat <span style="font-weight: bold; ">on the</span> mat';
DECLARE @Search VARCHAR(50) = 'is a nice';
;WITH Search_CTE (html_id, html_text)
AS (
SELECT h.id AS 'html_id'
, LEFT(h.html,REPLACE(PATINDEX('%<%',h.html)-1,-1,999999)) + SUBSTRING(h.html,CONVERT(INT,REPLACE(PATINDEX('%>%',h.html)+1,1,999999)),LEN(h.html)) AS 'html_text'
FROM @HTML AS h
WHERE h.html LIKE '%' + REPLACE(@Search,' ','%') + '%'
UNION ALL
SELECT c.html_id AS 'html_id'
, LEFT(c.html_text,REPLACE(PATINDEX('%<%',c.html_text)-1,-1,999999)) + SUBSTRING(c.html_text,CONVERT(INT,REPLACE(PATINDEX('%>%',c.html_text)+1,1,999999)),LEN(c.html_text)) AS 'html_text'
FROM Search_CTE AS c
WHERE PATINDEX('%<%',c.html_text) > 0
)
SELECT h.html AS 'Original HTML'
, cte.html_text AS 'HTML Text'
FROM Search_CTE AS cte
JOIN @HTML AS h
ON h.id = cte.html_id
WHERE PATINDEX('%<%',cte.html_text) = 0
AND html_text LIKE '%' + @Search + '%';
这个查询有一个限制,它不能处理文本中包含 > 或 < 的情况,但如果需要的话,可以编写代码来解决这个问题。
LIKE
子句非常有限,正如您的问题所生动展示的那样。精心实施的全文索引可能不是完美的,但它可以扩展简单索引和查询所能达到的边界。 - kbrimington