0

我需要对 SQL Server 2008 R2 数据库中 1 到 3 个字段中的子字符串执行全文搜索。仅必须搜索具有非空搜索词的字段。我使用实体框架,搜索是更大的 LINQ 查询的一部分,所以它必须在表值函数中完成才能组合。因此,不可能有动态 SQL。到目前为止,我提出了以下 UDF:

CREATE FUNCTION [dbo].[SearchPublications] 
(
@version int,
@comment nvarchar(4000),
@description nvarchar(4000),
@tags nvarchar(4000)
)
RETURNS 
@Table_Var TABLE 
(
[ID] [int] NOT NULL,
[IDPublicationType] [int] NOT NULL,
[IDCover] [int] NULL,
[IDSmallCover] [int] NULL,
[IDContent] [int] NOT NULL,
[Cost] [decimal](10, 2) NOT NULL,
[Language] [smallint] NOT NULL,
[Flags] [tinyint] NOT NULL,
[Year] [smallint] NOT NULL,
[Guid] [nvarchar](255) NOT NULL,
[Key] [nvarchar](25) NOT NULL,
[CTime] [datetime] NOT NULL
)
AS
BEGIN
declare @commentParam nvarchar(4000), @descriptionParam nvarchar(4000), @tagsParam nvarchar(4000), @guid nvarchar(32) = 'E442FB8EA8624E289BD13753480AFA8B'
select @commentParam = isnull('"' + @comment + '*"', @guid)
select @descriptionParam = isnull('"' + @description + '*"', @guid)
select @tagsParam = isnull('"' + @tags + '*"', @guid)

insert @Table_Var
select *
from Publications
where (@commentParam = @guid or exists (select
1 from PublicationFields
where IDPublication = Publications.ID and IDField = 3 and IDVersion = @version and
contains(LongValue, @commentParam)
))
and (@descriptionParam = @guid or exists (select
1 from PublicationFields
where IDPublication = Publications.ID and IDField = 4 and IDVersion = @version and
contains(LongValue, @descriptionParam)
))
and (@tagsParam = @guid or exists (select
1 from PublicationFields
where IDPublication = Publications.ID and IDField = 5 and IDVersion = @version and
contains(LongValue, @tagsParam))
)
RETURN 
END

但是,使用@param = @guid or...构造从搜索中排除空参数会导致查询计划非常不理想,并且搜索最多需要 10 秒才能完成。没有上述结构的相同搜索几乎立即返回,但在这种情况下,我不能使用可变数量的搜索词。当动态 SQL 不可行时,是否有更优化的方法从查询中排除 WHERE 子句的一部分?我想避免为 3 个搜索参数的每个组合编写单独的 TVF。

4

1 回答 1

0

回答我自己的问题:解决方案是编写一个只搜索一个指定字段的函数

CREATE FUNCTION [dbo].[SearchPublications]
(   
    @version int,
    @field int,
    @search nvarchar(4000)
)
RETURNS TABLE 
AS
RETURN 
(
    select Publications.*
    from Publications, PublicationFields
    where IDPublication = Publications.ID and IDField = @field and IDVersion = @version and
    contains(LongValue, @search)
)

然后使用 Intersect 方法在 LINQ 查询中根据需要组合尽可能多的调用:

if (query == null)
{
     query = provider.SearchPublications(search.IDVersion, id, string.Format("\"{0}*\"", value));
}
else
{
     query = query.Intersect(provider.SearchPublications(search.IDVersion, id, string.Format("\"{0}*\"", value)));
}
于 2013-01-16T16:22:56.600 回答