SQL Server CONTAINS Predicate - 使用列值作为 <contains_condition>

Posted

技术标签:

【中文标题】SQL Server CONTAINS Predicate - 使用列值作为 <contains_condition>【英文标题】:SQL Server CONTAINS Predicate - using a column value as the <contains_condition> 【发布时间】:2013-09-29 17:33:19 【问题描述】:

我在重写使用CONTAINS 谓词的现有进程时遇到问题。现有进程正在使用CURSOR,但它确实很慢,并且随着插入更多数据而变得更慢。

我编写了一个简单的示例(代码如下),其中包含两个表 - 一个是全文索引,另一个具有标识CONTAINS 条件的列,可以从第一个表中选择行.

当前存储过程使用CURSOR 循环第二个表,设置@filter 变量,然后使用CONTAINS 查找第一个表中匹配的行。问题是它运行了几个小时,而且情况越来越糟。

为了加快处理速度,我尝试直接在列值上使用CONTAINS 谓词,而不是经历游标的痛苦……但我遇到了语法错误。我的例子如下。

我尝试实现CROSS APPLY,也尝试编写用户定义函数 (fnCONTAINS),但没有成功。

IF ( object_id('Players') IS NOT NULL )
  DROP TABLE Players

go

IF ( object_id('TeamNeeds') IS NOT NULL )
  DROP TABLE TeamNeeds

go

-- create fulltext catalog ft as default
go

CREATE TABLE Players
  (
     PlayerID        INT IDENTITY(1, 1),
     PlayerName      VARCHAR(20),
     PlayerPositions VARCHAR(60)
  )

go

CREATE UNIQUE INDEX IXPlayerID
  ON Players( PlayerID )

go

CREATE fulltext INDEX ON Players(PlayerPositions) KEY INDEX IXPlayerID

go

INSERT Players
       (PlayerName,
        PlayerPositions)
VALUES( 'Patrick Travers',
        'Pitcher,Left Field,Center Field,Right Field,Shortstop' )

go

CREATE TABLE TeamNeeds
  (
     TeamID   INT,
     Keywords VARCHAR(50)
  )

go

INSERT TeamNeeds
       (TeamID,
        Keywords)
VALUES( 1,
        '"Center Field" and "Shortstop" and "Pitcher"' )

go

WAITFOR delay '00:00:05'

go -- Give the Full Text Index process time to populate the catalog
SELECT PlayerID,
       PlayerName,
       PlayerPositions
FROM   Player,
       TeamNeeds
WHERE  CONTAINS(PlayerPositions, Keywords)

go -- Syntax error on Keywords...
SELECT PlayerID,
       PlayerName,
       PlayerPositions
FROM   Players,
       TeamNeeds
WHERE  CONTAINS(PlayerPositions, '"Center Field" and "Shortstop" and "Pitcher"')

go -- Works just fine, but requires setting an explicit search expression for every search, which is terribly slow

【问题讨论】:

我删除了注释分隔符,使您的代码更具可读性。 我也一直想回答这个问题。我查看了***和ms的文档,但看起来你不能做CONTAINS(table1.col,table2.col)。你只能做 CONTAINS(table1.col, 'text') 或 CONTAINS(table1.col, @some_text)。我希望有人来证明我错了。 你想好如何解决这个问题了吗?我遇到了完全相同的问题。 【参考方案1】:

据我所知,这仅适用于多语句 TVF。

创建以下函数

CREATE FUNCTION [dbo].[ft_test] (@Keywords VARCHAR(50))
RETURNS @ReturnTable TABLE (
  PlayerID        INT,
  PlayerName      VARCHAR(20),
  PlayerPositions VARCHAR(60))
AS
  BEGIN
      INSERT INTO @ReturnTable
      SELECT PlayerID,
             PlayerName,
             PlayerPositions
      FROM   Players
      WHERE  CONTAINS(PlayerPositions, @Keywords)

      RETURN
  END

然后以下工作正常

SELECT *
FROM   TeamNeeds
       CROSS APPLY [dbo].[ft_test] (Keywords) CA 

尽管内联版本失败并显示“内联函数“x”不能采用相关参数或子查询,因为它使用了全文运算符。”

【讨论】:

以上是关于SQL Server CONTAINS Predicate - 使用列值作为 <contains_condition>的主要内容,如果未能解决你的问题,请参考以下文章

使用 Contains() 时达到 2100 参数限制 (SQL Server)

SQL Server CONTAINS Predicate - 使用列值作为 <contains_condition>

如何强制 SQL Server 在 WHERE 子句之前处理 CONTAINS 子句?

将 SQL Server 的 CONTAINS() 作为模型定义函数导入

对于 CONTAINS 全文谓词,SQL Server 2008 中的逻辑短路似乎失败

Is contains 相当于 SQL Server 中的 Like