将输入的多个变体匹配到一个sql行

时间:2011-10-05 12:42:12

标签: sql sql-server-2005 tsql sqlclr

我想知道很多搜索后如何使用标准TSQL将输入的不同变体匹配到一个sql行。这是场景:

我的sql行中有以下文字:I love

然后,我有以下3个输入,所有这些输入应该返回到此行的匹配项:

  

" 想告诉大家我们都 StackOverflow"

     

" '完全在与StackOverflow"

     

" 真的 StackOverflow"

正如你所看到的,我已经加粗了比赛的原因,试图让你更清楚为什么他们匹配。 I中的I'm也是故意匹配的,所以如果我们可以在匹配中包含它,那将会很好。

我考虑过使用以下TSQL分割输入字符串:

-- Create a space delimited string for testing
declare @str varchar(max)
select @str = 'I want to tell you we all love StackOverflow'
-- XML tag the string by replacing spaces with </x><x> tags
declare @xml xml
select @xml = cast('<x><![CDATA['+ replace(@str,' ',']]></x><x><![CDATA[') + ']]></x>' as xml)
-- Finally select values from nodes <x> and trim at the same time
select ltrim(rtrim(mynode.value('.[1]', 'nvarchar(12)'))) as Code
from (select @xml doc) xx
cross apply doc.nodes('/x') (mynode)

这会将我的所有单词作为单独的行,但后来我无法确定如何进行匹配这些查询。

因此,从这一点获得任何帮助或根据需要进行任何其他匹配方式都会非常感激!

更新

@freefaller向我指出了RegEx路由并创建了一个我已经能够进一步向前推进的函数,因此+1 @freefaller,但我现在需要知道如何让它来查看我的所有表行而不是硬编码的输入,我喜欢&#39;我现在有以下select语句:

SELECT * FROM dbo.FindWordsInContext('i love','I want to tell you we all love StackOverflow',30)
SELECT * FROM dbo.FindWordsInContext('i love','I''m totally in love with StackOverflow',30)
SELECT * FROM dbo.FindWordsInContext('i love','I really love StackOverflow',30)

以上返回匹配的次数和匹配的字符串的上下文,因此上面的第一个选择返回:

Hits    Context
1       ...I want to tell you we all love StackOv...

所以基于我们现在有上述事实可以告诉我如何让这个函数查看匹配的所有行,然后返回匹配的行/行?

2 个答案:

答案 0 :(得分:1)

一种选择是通过SQLCLR对象as explained here使用正则表达式。

我从未自己创建过SQLCLR对象,因此无法对此方法的易用性发表评论。然而,我是正则表达式的忠实粉丝,并建议将它们用于大多数文本搜索/操作

编辑:在回复评论时,我没有SQLCLR的经验,但假设您正常工作,可能会有以下简单的未经测试的 TSQL。

SELECT *
FROM mytable
WHERE dbo.RegexMatch(@search, REPLACE(myfield, ' ', '.*?')) = 1

答案 1 :(得分:1)

我已经设法回答了我自己的问题,所以我想我会发布这里以防万一其他人在将来有类似的要求。基本上它依赖于SQL-CLR正则表达式功能,并且对性能的影响最小。

首先在您的服务器上启用SQL-CLR(如果尚未提供)(您需要是sysadmin):

--Enables CLR Integration
exec sp_configure 'clr enabled', 1
GO
RECONFIGURE
GO

然后,您需要在SQL中创建程序集(不要忘记从D:\SqlRegEx.dll更改路径并使用SAFE权限集,因为这是最严格且最安全的权限集,但赢了这里不详细说明。):

CREATE ASSEMBLY [SqlRegEx] FROM 'D:\SqlRegEx.dll' WITH PERMISSION_SET = SAFE

现在创建您将调用的实际函数:

CREATE FUNCTION [dbo].[RegexMatch]
(@Input NVARCHAR(MAX), @Pattern NVARCHAR(MAX), @IgnoreCase BIT)
RETURNS BIT
AS EXTERNAL NAME SqlRegEx.[SqlClrTools.SqlRegEx].RegExMatch

最后,为了完成并回答我自己的问题,我们可以运行以下TSQL:

SELECT *
FROM your_table
WHERE dbo.RegexMatch(@search, REPLACE(your_field, ' ', '.*?'), 1) = 1
SELECT *
FROM your_table
WHERE dbo.RegexMatch(@search, REPLACE(REVERSE(your_field), ' ', '.*?'), 1) = 1

我希望这将有助于某人在未来应该是一个简单的搜索选项。