告诉我 SQL Server 全文搜索器疯了,不是我疯了

2024-05-19

我有一些客户具有用户正在搜索的特定地址:

123 通用方式

数据库中有 5 行匹配:

ResidentialAddress1
=============================
123 GENERIC WAY
123 GENERIC WAY
123 GENERIC WAY
123 GENERIC WAY
123 GENERIC WAY

我运行 FT 查询来查找这些行。当我向搜索添加更多条件时,我将向您展示每个步骤:

SELECT ResidentialAddress1 FROM Patrons
WHERE CONTAINS(Patrons.ResidentialAddress1, '"123*"')

ResidentialAddress1
=========================
123 MAPLE STREET
12345 TEST
123 MINE STREET
123 GENERIC WAY
123 FAKE STREET
...

(30 row(s) affected)

好的,到目前为止一切顺利,现在添加这个词“generic":

SELECT ResidentialAddress1 FROM Patrons
WHERE  CONTAINS(Patrons.ResidentialAddress1, '"123*"')
AND CONTAINS(Patrons.ResidentialAddress1, '"generic*"')

ResidentialAddress1
=============================
123 GENERIC WAY
123 GENERIC WAY
123 GENERIC WAY
123 GENERIC WAY
123 GENERIC WAY

(5 row(s) affected)

出色的。现在我将添加用户想要确保存在的最终关键字:

SELECT ResidentialAddress1 FROM Patrons
WHERE  CONTAINS(Patrons.ResidentialAddress1, '"123*"')
AND CONTAINS(Patrons.ResidentialAddress1, '"generic*"')
AND CONTAINS(Patrons.ResidentialAddress1, '"way*"')


ResidentialAddress1            
------------------------------ 

(0 row(s) affected)

啊?没有行?如果我只查询“way*”怎么办:

SELECT ResidentialAddress1 FROM Patrons
WHERE CONTAINS(Patrons.ResidentialAddress1, '"way*"')

ResidentialAddress1            
------------------------------ 

(0 row(s) affected)

起初我想也许是因为*,并且它要求根way后面还有更多字符。但事实并非如此:

  • 搜索“123*”匹配“123”
  • 搜索“generic*”与“generic”匹配
  • 网上的书说,星号匹配零个、一个或多个字符

如果我删除怎么办*仅适用于 s&g:

SELECT ResidentialAddress1 FROM Patrons
WHERE CONTAINS(Patrons.ResidentialAddress1, '"way"')

Server: Msg 7619, Level 16, State 1, Line 1
A clause of the query contained only ignored words. 

所以人们可能会认为你甚至不被允许search for way,可以单独使用,也可以作为根使用。但这也不是真的:

SELECT * FROM Patrons
WHERE CONTAINS(Patrons.*, '"way*"')

AccountNumber FirstName Lastname
------------- --------- --------
33589         JOHN      WAYNE                    

综上所述,用户正在搜索包含所有单词的行:

123 通用方式

我正确地翻译成WHERE条款:

SELECT * FROM Patrons
WHERE CONTAINS(Patrons.*, '"123*"')
AND CONTAINS(Patrons.*, '"generic*"')
AND CONTAINS(Patrons.*, '"way*"')

它不返回任何行。告诉我这行不通,这不是我的错,而且 SQL Server 太疯狂了。

Note:我已经清空了 FT 索引并重建了它。

更新一

SELECT Lastname, ResidentialAddress1 FROM Patrons
WHERE CONTAINS(Patrons.*, '"gen*"')

Lastname                  ResidentialAddress1            
------------------------- ------------------------------ 
SAVE                      123 GENERIC WAY
Genders                   
SAVE                      123 GENERIC WAY
Patron                    123 GENERIC WAY
SAVE                      123 GENERIC WAY
SAVE                      234 GENERIC WAY
SAVE                      123 GENERIC WAY

(7 row(s) affected)

更新二

假装用户输入:

123 通用瓦

SELECT ResidentialAddress1 FROM Patrons
WHERE  CONTAINS(Patrons.ResidentialAddress1, '"123*"')
AND CONTAINS(Patrons.ResidentialAddress1, '"generic*"')
AND CONTAINS(Patrons.ResidentialAddress1, '"wa*"')

ResidentialAddress1            
------------------------------ 

(0 row(s) affected)

真正的问题是用户正在输入完全有效的内容,并且他们希望看到任何人都希望看到的内容。


更新三

有人要求这一切,这不是我的错!:

CREATE TABLE [dbo].[Patrons] (
    [PatronGUID]  uniqueidentifier ROWGUIDCOL  NOT NULL ,
    [AccountNumber] [bigint] NULL ,
    [FirstName] [varchar] (25) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [MiddleInitial] [varchar] (1) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [Lastname] [varchar] (25) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [EyeColor] [varchar] (30) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [HairColor] [varchar] (30) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [Gender] [varchar] (1) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [Birthday] [datetime] NULL ,
    [Height] [int] NULL ,
    [Weight] [int] NULL ,
    [FacialHair] [tinyint] NULL ,
    [Nationality] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [IdentifyingMarks] [varchar] (30) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [DriversLicenseNumber] [varchar] (25) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [DriversLicenseRegion] [varchar] (20) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [DriversLicenseCountry] [varchar] (2) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [DriversLicenseExpires] [datetime] NULL ,
    [DriversLicenseDateVerified] [datetime] NULL ,
    [PassportNumber] [varchar] (25) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [PassportRegion] [varchar] (20) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [PassportCountry] [varchar] (2) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [PassportExpires] [datetime] NULL ,
    [PassportDateVerified] [datetime] NULL ,
    [OtherIdentificationNumber] [varchar] (25) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [OtherIdentificationRegion] [varchar] (20) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [OtherIdentificationCountry] [varchar] (2) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [OtherIdentificationType] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [OtherIdentificationExpires] [datetime] NULL ,
    [OtherIdentificationDateVerified] [datetime] NULL ,
    [ResidentialAddress1] [varchar] (30) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [ResidentialAddress2] [varchar] (30) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [ResidentialAddress3] [varchar] (30) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [ResidentialCity] [varchar] (25) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [ResidentialZipCode] [varchar] (15) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [ResidentialRegion] [varchar] (20) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [ResidentialCountry] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [ResidentialPhoneNumber] [varchar] (20) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [CountryOfResidence] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [BusinessAddress1] [varchar] (30) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [BusinessAddress2] [varchar] (30) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [BusinessAddress3] [varchar] (30) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [BusinessCity] [varchar] (25) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [BusinessRegion] [varchar] (20) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [BusinessZipCode] [varchar] (15) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [BusinessCountry] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [BusinessName] [varchar] (25) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [BusinessPhone] [varchar] (20) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [PositionWithFirm] [varchar] (30) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [EmployerTelephone] [varchar] (20) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [MemberCardType] [varchar] (1) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [PlayerStatusCode] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [AccountType] [varchar] (1) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [AccountStatus1] [varchar] (1) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [AccountStatus2] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [IsVIPExchangeRate] [tinyint] NULL ,
    [ChangedUserGUID_Depricated] [uniqueidentifier] NULL ,
    [ChangedUser] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [ChangedDate] [datetime] NULL ,
    [ChangedWorkstation] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [PendingUpdates_Depricated] [varchar] (255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[Patrons] ADD 
    CONSTRAINT [DF_Patrons_PatronGUID] DEFAULT (newid()) FOR [PatronGUID],
    CONSTRAINT [PK_Patrons] PRIMARY KEY  NONCLUSTERED 
    (
        [PatronGUID]
    ) WITH  FILLFACTOR = 90  ON [PRIMARY] 
GO

if (select DATABASEPROPERTY(DB_NAME(), N'IsFullTextEnabled')) <> 1 
exec sp_fulltext_database N'enable' 

GO

if not exists (select * from dbo.sysfulltextcatalogs where name = N'TheFullTextCatalog')
exec sp_fulltext_catalog N'TheFullTextCatalog', N'create' 

GO

exec sp_fulltext_table N'[dbo].[Patrons]', N'create', N'TheFullTextCatalog', N'PK_Patrons'
GO

exec sp_fulltext_column N'[dbo].[Patrons]', N'FirstName', N'add', 1033  
GO

exec sp_fulltext_column N'[dbo].[Patrons]', N'MiddleInitial', N'add', 1033  
GO

exec sp_fulltext_column N'[dbo].[Patrons]', N'Lastname', N'add', 1033  
GO

exec sp_fulltext_column N'[dbo].[Patrons]', N'EyeColor', N'add', 1033  
GO

exec sp_fulltext_column N'[dbo].[Patrons]', N'IdentifyingMarks', N'add', 1033  
GO

exec sp_fulltext_column N'[dbo].[Patrons]', N'ResidentialAddress1', N'add', 1033  
GO

exec sp_fulltext_column N'[dbo].[Patrons]', N'ResidentialAddress2', N'add', 1033  
GO

exec sp_fulltext_column N'[dbo].[Patrons]', N'ResidentialAddress3', N'add', 1033  
GO

exec sp_fulltext_column N'[dbo].[Patrons]', N'ResidentialCity', N'add', 1033  
GO

exec sp_fulltext_column N'[dbo].[Patrons]', N'ResidentialZipCode', N'add', 1033  
GO

exec sp_fulltext_column N'[dbo].[Patrons]', N'ResidentialRegion', N'add', 1033  
GO

exec sp_fulltext_column N'[dbo].[Patrons]', N'ResidentialCountry', N'add', 1033  
GO

exec sp_fulltext_column N'[dbo].[Patrons]', N'ResidentialPhoneNumber', N'add', 1033  
GO

exec sp_fulltext_column N'[dbo].[Patrons]', N'CountryOfResidence', N'add', 1033  
GO

exec sp_fulltext_table N'[dbo].[Patrons]', N'activate'  
GO

以下是给那些不相信我的人的截图:

应该有效但无效的查询:

该查询有效,但没有用:

带有证明内容的查询有效,但没有用:


更新四

查询cannot写成

CONTAINS(Patrons.*, 'words...')

因为有些项目在逻辑上或物理上没有被 FT 索引涵盖。例如用户查询 为了:

6/4/2010 伊恩·博伊德 619

提出四个关键词:

  • 6/4/2010
  • ian
  • boyd
  • 619

这意味着他们希望所有条件都成立,伪代码为:

WHERE 6/4/2010 is in the row
AND ian is in the row
AND boyd is in the row
AND 619 is in the row

这被翻译成以下部分查询:

WHERE --Keyword 1: 6/4/2010
(
   ((ChangedDate >= '20100604') AND (ChangedDate < '20100605'))
   OR 
   ((LastTransactionDate >= '20100604') AND (LastTransactionDate < '20100605'))
   OR 
   (CONTAINS(Patrons.*, '"6/4/2010*"')
)
AND --Keyword 2: ian
(
    CONTAINS(Patrons.*, '"ian*"')
)
AND --Keyword 3: boyd
(
    CONTAINS(Patrons.*, '"boyd*"')
)
AND --Keyword 4: 619
(
    (AccountNumber IN (SELECT CAST(619 AS bigint)))
    OR
    (CONTAINS(Patrons.*, '"619*"'))
)

其中一位回答者正在查看原始问题中提出的简化示例;不是现实世界。要说它是不正确拥有多个AND条款是nieve。


该消息告诉您“way”是一个停用词,这意味着它会被忽略并且不会被索引。这就是为什么你可以找到“wayne”但找不到“way”。

所以,不,这并不疯狂,你也不是。这只是一个简单的误会。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

告诉我 SQL Server 全文搜索器疯了,不是我疯了 的相关文章

  • 将单个列连接到逗号分隔的列表中[重复]

    这个问题在这里已经有答案了 我已经看到了人们将单个列滚动到逗号分隔列表中的多个示例 但我需要更多 这是我需要的数据和结果的示例 DECLARE SalesPerson table SalesPersonID int SalesPersonN
  • mySQL MATCH 跨多个表

    我有一组 4 个表 我想对其进行搜索 每个都有全文索引 查询可以使用每个索引吗 CREATE TABLE categories id int 5 unsigned NOT NULL auto increment display order
  • 设置 xact_abort 并尝试一起捕获

    我的 sp 中有一个 try catch 块 其中只有一条插入语句 catch 检查错误代码是否违反 pk 如果是则进行更新 但有时我得到 当前事务无法提交 并且无法支持写入日志文件的操作 回滚事务 在批处理结束时检测到不可提交的事务 事务
  • 如何在 SQL Server 中的特定字符后分割字符串并将该值更新到特定列

    我有包含数据的表格1 1 to 1 20在一列中 我想要值 1 到 20 即 前斜杠 之后的值更新到 SQL Server 中同一表中的其他列 Example 专栏有价值1 1 1 2 1 3 1 20新列值1 2 3 20 也就是说 我要
  • 连接两个表的查询的 SQL Server“FOR XML”输出

    我是 SQL Server 中 FOR XML 功能的新手 我正在使用 SQL Server 2012 我有两个表 Word 和 Word Expansion 样本数据 表 字 WordOID Word 1 PIPE 2 WIRE 表 Wo
  • Scrapy - 如何抓取网站并将数据存储在 Microsoft SQL Server 数据库中?

    我正在尝试从我们公司创建的网站中提取内容 我在 MSSQL Server 中为 Scrapy 数据创建了一个表 我还设置了 Scrapy 并配置了 Python 来抓取和提取网页数据 我的问题是 如何将Scrapy爬取的数据导出到我本地的M
  • SQL服务器事务

    我需要了解sql server事务 我浏览了谷歌上的一些文章 但我什么也没理解 谁能帮我 您可以通过写入显式启动事务BEGIN TRANSACTION 您可以通过运行来结束事务COMMIT TRANSACTION 之前COMMIT运行时 受
  • Kerberos 双跳

    我们遇到了臭名昭著的 Kerberos 双跳问题 这是一个全新的域 是从以前使用模拟和委派的另一个提供商迁移而来的 我们已将操作系统升级到最新的 SQL 服务器 2017 WPF 应用程序 使用域凭据 gt Web 服务 IIS 10 上的
  • 列中差异的数量

    我想检索一列每行中有多少个字母的差异 例如 如果您有一个值 test 而另一行有一个值 testing 则 test 和 testing 之间的差异为 4 个字母 该列的数据值为 4 I have reflected about it an
  • 有没有办法以编程方式轻松更改多个 SSIS 包上的服务器名称?

    作为发布周期的一部分 我们正在创建多个 SSIS 包来迁移大型数据库 我们最终可能会得到大约 5 10 个 SSIS 包 由于我们有 4 个环境 开发 QA 登台 生产等 是否有一种有效的方法可以在每个 SSIS 包经历不同的服务器环境时更
  • 对多个数据库执行 SQL 查询

    我知道我的帖子与该论坛中的其他帖子的标题非常相似 但我真的找不到我需要的答案 这是我的问题 我的 Windows Server 上运行着 SQL Server 在我的 SQL Server 中 我有大约 30 个数据库 它们都具有相同的表和
  • 选择具有 SQL Server XML 列类型的特定行

    我正在尝试从类似于以下定义的表中选择数据 Column Data Type Id Int DataType Int LoggedData XML 但我只想选择具有特定 DataType 值并且在 LoggedData 列中包含字符串 或评估
  • C#的数组列表可以用来填充SSIS对象变量吗?

    我已在 C 脚本中填充了一个列表 并将其值分配给 SSIS 对象变量 然后 我使用该对象变量通过循环遍历 For every do 枚举器来执行一些 SQL 查询 我尝试通过 Foreach ado 枚举器执行此操作 但出现错误 X 变量不
  • 临时表是线程安全的吗?

    我正在使用 SQL Server 2000 它的许多存储过程广泛使用临时表 数据库的流量很大 我担心创建和删除临时表的线程安全性 假设我有一个存储过程 它创建了一些临时表 它甚至可以将临时表连接到其他临时表等 并且还可以说两个用户同时执行存
  • 为什么我的 CASE 语句要求 THEN 部分的数据类型为 INT?

    我正在尝试运行一个查询 其中以下 CASE 语句是其中一行 我正在使用报表生成器 3 0 但是 我收到一条错误消息 将 varchar 值 Case 1 转换为 int 数据类型时转换失败 Microsoft SQL Server 错误 2
  • SQL - != 'NULL' 的解释

    我的SSMS代码如下 Select top 50 From FilteredContact Where statuscode 1 and emailaddress1 NULL and telephone1 NULL and address1
  • VB6+SQL-Server:如何使用 ADODB.Command 执行带有命名参数的查询?

    我一直在尝试使用 ADODB Command 执行参数化查询 我知道我可以使用 对于参数 但我的查询相当大 我真的不想跟踪参数的确切顺序 我尝试了类似以下的操作 objCmd CommandType adCmdText objCmd Com
  • 普通表还是全局临时表?

    我和另一位开发人员正在讨论哪种类型的表更适合我们的任务 它基本上是一个我们将在一天结束时截断的缓存 就我个人而言 我认为没有任何理由为此使用除普通表之外的任何内容 但他想使用全局临时表 其中之一有什么优点吗 使用普通表tempdb如果这只是
  • 插入后,数据库中仅插入“字符串”的一个字符

    Below is my table screenshot Data after insertion C 代码 SqlConnection con new SqlConnection connectionsession Con con Ope
  • 如何避免使用 Cursor 来实现此伪代码 - SQL Server

    CREATE PROCEDURE p processDataFor accountId BEGIN for each item in select from Accounts where accountId accountId and is

随机推荐