Ampliando la idea de Ishmael, no es la solución final, pero creo que es una buena forma de empezar.
En primer lugar, necesitamos obtener la lista de palabras que se han recuperado con el motor de texto completo:
declare @SearchPattern nvarchar(1000) = 'FORMSOF (INFLECTIONAL, " ' + @SearchString + ' ")'
declare @SearchWords table (Word varchar(100), Expansion_type int)
insert into @SearchWords
select distinct display_term, expansion_type
from sys.dm_fts_parser(@SearchPattern, 1033, 0, 0)
where special_term = 'Exact Match'
Ya hay mucho que se puede ampliar, por ejemplo, el patrón de búsqueda es bastante básico; También hay probablemente mejores formas de filtrar las palabras que no necesita, pero al menos le da una lista de palabras raíz, etc. que coincidirían con la búsqueda de texto completo.
Después de obtener los resultados que necesita, puede usar RegEx para analizar el conjunto de resultados (o preferiblemente solo un subconjunto para acelerarlo, aunque todavía no he descubierto una buena manera de hacerlo). Para esto, simplemente uso dos bucles while y un montón de tablas y variables temporales:
declare @FinalResults table
while (select COUNT(*) from @PrelimResults) > 0
begin
select top 1 @CurrID = [UID], @Text = Text from @PrelimResults
declare @TextLength int = LEN(@Text )
declare @IndexOfDot int = CHARINDEX('.', REVERSE(@Text ), @TextLength - dbo.RegExIndexOf(@Text, '\b' + @FirstSearchWord + '\b') + 1)
set @Text = SUBSTRING(@Text, case @IndexOfDot when 0 then 0 else @TextLength - @IndexOfDot + 3 end, 300)
while (select COUNT(*) from @TempSearchWords) > 0
begin
select top 1 @CurrWord = Word from @TempSearchWords
set @Text = dbo.RegExReplace(@Text, '\b' + @CurrWord + '\b', '<b>' + SUBSTRING(@Text, dbo.RegExIndexOf(@Text, '\b' + @CurrWord + '\b'), LEN(@CurrWord) + 1) + '</b>')
delete from @TempSearchWords where Word = @CurrWord
end
insert into @FinalResults
select * from @PrelimResults where [UID] = @CurrID
delete from @PrelimResults where [UID] = @CurrID
end
Varias notas:
1. Los bucles while anidados probablemente no sean la forma más eficiente de hacerlo, sin embargo, no se me ocurre nada más. Si tuviera que usar cursores, ¿sería esencialmente lo mismo?
2. @FirstSearchWord
aquí a se refiere a la primera instancia en el texto de una de las palabras de búsqueda originales, por lo que esencialmente el texto que está reemplazando solo estará en el resumen. Una vez más, es un método bastante básico, probablemente sería útil algún tipo de algoritmo de búsqueda de grupos de texto.
3. Para obtener RegEx en primer lugar, necesita las funciones definidas por el usuario de CLR.