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

发布于 2024-11-04 21:09:46 字数 863 浏览 0 评论 0原文

下面是我的 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 参数传递空值或 null 值,以便全文搜索返回所有记录。但是当我传递空值或空值时,我收到“空或空全文谓词”错误。经过谷歌搜索后,我发现 CONTAINSTABLE 不能为关键字采用空参数。我也看到过这个 问题 但它对我没有帮助。

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

Below is a simplified version of my sql query that uses CONTAINSTABLE for full text searching.

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]

I want to pass empty or null value for @pSearchFor parameter so that all records are returned by full text search. But I get a "Null or empty full-text predicate" error when I pass empty or null value. After googling, I found that CONTAINSTABLE cannot take an empty parameter for keywords. I have also seen this question in SO but it did not help me.

Can I make a conditional join with CONTAINSTABLE (only when a value is specified for @pSearchFor parameter)?. I am not sure how to achieve this. Would appreciate any pointers.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

So要识趣 2024-11-11 21:09:46
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

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

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

I just solved the exact same issue and thought of helping you out.

要走就滚别墨迹 2024-11-11 21:09:46

当您搜索空值或 null 值时,您期望得到什么?您希望查询不返回任何内容,还是希望它返回其他内容。

如果您希望它不返回任何内容,那么您最好执行以下操作:

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

编辑:固定为现在在提供 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 表的结果,因为它会对于较大的表来说会变慢。

What do you expect to get when you search for an empty or null value? do you expect the query to return nothing or do you expect it to return something else.

If you want it to return nothing then you're best of doing something like this:

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 return all records when null or empty string is supplied.

If you have more than 2 CONTAINS table queries with different search strings, then I would suggest you generate the query using dynamic SQL as it would be much easier to maintain than a 2^n chain of almost the same queries

Edit: having looked at a way to do this without using multiple copies by using a temp table like this:

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]

This should give you what you want without having to duplicate things, however you might want to restrict the result that is fed into the #temp table some more as it will get slow for larger tables.

四叶草在未来唯美盛开 2024-11-11 21:09:46

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

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

I had also the exact same issue and solved it by adding/appending a dummy keyword 'fts' to the search indexed column for all the records.

if(nullif(@pSearchFor,'') is null)
begin
     set @pSearchFor= 'fts';                
end
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文