SQL Server - 使用空关键字进行自由文本搜索

时间:2011-05-03 21:29:09

标签: sql-server sql-server-2008 full-text-search containstable

以下是我的SQL查询的简化版本,它使用 CONTAINSTABLE 进行全文搜索。

DECLARE @pSearchFor AS NVARCHAR(100);
SET @pSearchFor = 'SomeKeyword';

SELECT MS.[ModuleScreenID] AS ScreenID
    ,MS.[ModuleScreenCode] AS ScreenCode
    ,M.[Description] AS ModuleDescription
    ,M.[ModuleCode] AS ModuleCode        
    ,FT.[Rank] 
FROM ModuleScreen MS
    JOIN Module M ON MS.ModuleID = M.ModuleID
    JOIN CONTAINSTABLE(ModuleScreen, *, @pSearchFor) FT ON MS.ModuleScreenID = FT.[KEY]

我想为@pSearchFor参数传递空值或空值,以便通过全文搜索 返回所有记录 。但是当我传递空值或空值时,我得到“空或全空谓词”错误。谷歌搜索后,我发现CONTAINSTABLE不能为关键字取一个空参数。我在SO中也看到了question,但它对我没有帮助。

我可以使用CONTAINSTABLE进行条件连接(仅当为@pSearchFor参数指定了值时)吗?我不知道如何实现这一目标。非常感谢任何指针。

3 个答案:

答案 0 :(得分:3)

DECLARE @pSearchFor AS NVARCHAR(100);

SET @pSearchFor = 'SomeKeyword';
--if @pSearch comes as parameter then --
set @pSearch = ISNULL(@pSearch,'*')

SELECT MS.[ModuleScreenID] AS ScreenID
    ,MS.[ModuleScreenCode] AS ScreenCode
    ,M.[Description] AS ModuleDescription
    ,M.[ModuleCode] AS ModuleCode        
    ,FT.[Rank] 
FROM ModuleScreen MS
    JOIN Module M ON MS.ModuleID = M.ModuleID
    JOIN CONTAINSTABLE(ModuleScreen, *, @pSearchFor) FT ON MS.ModuleScreenID = FT.[KEY]
where @pSearchFor = '*' OR FT.[KEY] is not null

我刚解决了完全相同的问题,并想到帮助你。

答案 1 :(得分:0)

搜索空值或空值时,您期望获得什么?你希望查询什么都不返回,或者你希望它返回别的东西。

如果你想要它什么都不返回那么你最好做这样的事情:

DECLARE @pSearchFor AS NVARCHAR(100);
SET @pSearchFor = 'SomeKeyword';

IF @pSearchFor IS NOT NULL AND @pSearchFor <> '' 
BEGIN
    SELECT MS.[ModuleScreenID] AS ScreenID
        ,MS.[ModuleScreenCode] AS ScreenCode
        ,M.[Description] AS ModuleDescription
        ,M.[ModuleCode] AS ModuleCode        
        ,FT.[Rank] 
    FROM ModuleScreen MS
        JOIN Module M ON MS.ModuleID = M.ModuleID
        JOIN CONTAINSTABLE(ModuleScreen, *, @pSearchFor) FT ON MS.ModuleScreenID = FT.[KEY]
END
ELSE
BEGIN
    SELECT MS.[ModuleScreenID] AS ScreenID
        ,MS.[ModuleScreenCode] AS ScreenCode
        ,M.[Description] AS ModuleDescription
        ,M.[ModuleCode] AS ModuleCode        
        ,FT.[Rank] 
    FROM ModuleScreen MS
        JOIN Module M ON MS.ModuleID = M.ModuleID
END

edit:fixed to now返回所有记录,当提供null或空字符串时。

如果你有超过2个包含不同搜索字符串的CONTAINS表查询,那么我建议你使用动态SQL生成查询,因为它比几乎相同查询的2 ^ n链更容易维护

编辑:通过使用像这样的临时表,看了一种不使用多个副本的方法:

DECLARE @pSearchFor AS NVARCHAR(100);
SET @pSearchFor = 'SomeKeyword';

SELECT * INTO #temp FROM CONTAINSTABLE(ModuleScreen, *, @pSearchFor)

SELECT MS.[ModuleScreenID] AS ScreenID
    ,MS.[ModuleScreenCode] AS ScreenCode
    ,M.[Description] AS ModuleDescription
    ,M.[ModuleCode] AS ModuleCode        
    ,FT.[Rank] 
FROM Module M
    JOIN ModuleScreen MS ON MS.ModuleID = M.ModuleID AND (
        (1 = CASE WHEN ISNULL(@pSearchFor, '') = '' THEN 1 ELSE 0 END
        OR CONTAINS(MS.*, @pSearchFor)
    LEFT OUTER JOIN #temp FT ON MS.ModuleScreenID = FT.[Key]

这应该可以为您提供所需的内容,而不必复制内容,但是您可能希望将更多内容限制在#temp表中,因为对于较大的表来说它会变慢。

答案 2 :(得分:-1)

我也有完全相同的问题,并通过在所有记录的搜索索引列中添加/附加虚拟关键字'fts'来解决它。

if(nullif(@pSearchFor,'') is null)
begin
     set @pSearchFor= 'fts';                
end