Ruu*_*ten 5 sql-server collation full-text-search sql-server-2012
我正在尝试使用停用词,以便全文索引器跳过某些单词。我可以在表sys.fulltext_stopwords 中添加这些停用词。
尝试在 SQL Server 2012 中获取停用词和系统停用词列表时遇到错误。我正在执行以下(简化的)查询:
SELECT sys.fulltext_stopwords.stopword
FROM sys.fulltext_stopwords
UNION
SELECT sys.fulltext_system_stopwords.stopword
FROM sys.fulltext_system_stopwords;
Run Code Online (Sandbox Code Playgroud)
我得到的错误信息是:
“无法解决 UNION 操作中“Latin1_General_CI_AS”和“Latin1_General_BIN”之间的排序规则冲突。”
我的查询中第一个 SELECT 语句的数据库排序规则是Latin1_General_CI_AS。master、model、msdb和tempdb数据库也是如此。
在什么地方Latin1_General_BIN 整理从何而来?看起来 sys.fulltext_system_stopwords 表有不同的排序规则,但为什么呢?
编辑:
我可以通过在查询中使用COLLATE来“解决”我的错误,如下所示:
SELECT sys.fulltext_stopwords.stopword COLLATE DATABASE_DEFAULT
FROM sys.fulltext_stopwords
UNION
SELECT sys.fulltext_system_stopwords.stopword COLLATE DATABASE_DEFAULT
FROM sys.fulltext_system_stopwords
Run Code Online (Sandbox Code Playgroud)
我看到系统停用词存储在资源数据库中,可以解释整理的差异。下一个问题是:为什么资源数据库中的排序规则与默认排序规则不同?
我的查询中第一个 SELECT 语句的数据库排序规则是Latin1_General_CI_AS。
嗯,不完全是。这个说法有几个问题:
当使用字符串文字、变量和来自 UDF 的返回值时,数据库的默认排序规则仅在查询中重要。并且,默认排序规则仅在没有使用列或COLLATE关键字时才重要。
SELECT 语句/查询,作为一个整体,不使用排序规则。每个字符串字段都分配了排序规则,并且查询中的每个字段都可以不同。
第一个/顶部查询中的列stopword没有使用Latin1_General_CI_AS排序规则(稍后会详细介绍)。
我看到系统停用词存储在资源数据库中,可以解释整理的差异。
来自不同数据库的列(或表达式)不一定解释排序规则的差异。如上所述,排序规则是针对查询的每个字段设置的,无论该字段来自表中的列还是表达式。排序规则通常从排序规则优先级自然派生:列排序规则覆盖文字和变量,COLLATE关键字覆盖两者。如果有冲突,那么你需要的COLLATE关键字。
这里的主要点,但问题在于,如果stopword在列sys.fulltext_system_stopwords来自一个列在一个表中在资源数据库(即mssqlsystemresource),或者如果它来自一种表达在一个视图中,其经由具有其归类组资源数据库COLLATE关键字,那么资源数据库的默认排序规则是无关紧要的。
我可以通过
COLLATE在查询中使用来“解决”我的错误
是的,COLLATE关键字是要走的路。但是,要解决此冲突,您只需COLLATE在一个查询中指定关键字,尽管哪个查询无关紧要。
例如,如果我运行没有COLLATE关键字的查询,我会得到:
SELECT ftsw.stopword
FROM sys.fulltext_stopwords ftsw
UNION
SELECT ftssw.stopword
FROM sys.fulltext_system_stopwords ftssw;
Run Code Online (Sandbox Code Playgroud)
消息 468,级别 16,状态 9,第 4 行
无法解决 UNION 操作中“SQL_Latin1_General_CP1_CI_AS”和“Latin1_General_BIN”之间的排序规则冲突。
因此,假设冲突在第二个(即底部)SELECT 语句中,我可以通过应用当前数据库的默认排序规则来修复它:
SELECT ftsw.stopword
FROM sys.fulltext_stopwords ftsw
UNION
SELECT ftssw.stopword COLLATE SQL_Latin1_General_CP1_CI_AS
FROM sys.fulltext_system_stopwords ftssw;
Run Code Online (Sandbox Code Playgroud)
这有效。但是,如果我们尝试放置COLLATE第一个 / 顶部 SELECT 会怎样:
SELECT ftsw.stopword COLLATE SQL_Latin1_General_CP1_CI_AS
FROM sys.fulltext_stopwords ftsw
UNION
SELECT ftssw.stopword
FROM sys.fulltext_system_stopwords ftssw;
Run Code Online (Sandbox Code Playgroud)
这也有效。事实上,以下两种方法也都有效:
SELECT ftsw.stopword COLLATE Hebrew_100_CI_AS
FROM sys.fulltext_stopwords ftsw
UNION
SELECT ftssw.stopword
FROM sys.fulltext_system_stopwords ftssw;
-- and:
SELECT ftsw.stopword
FROM sys.fulltext_stopwords ftsw
UNION
SELECT ftssw.stopword COLLATE Hebrew_100_CI_AS
FROM sys.fulltext_system_stopwords ftssw;
Run Code Online (Sandbox Code Playgroud)
此外,在这种特殊情况下,我不会使用DATABASE_DEFAULT这里等同于Latin1_General_CI_AS的选项,而是使用Latin1_General_BIN(或者更好的是:Latin1_General_100_BIN2,它更新更好),因为它将确保可以将不同的字符串规范化为相同的字符串通过UNION(没有ALL)的“不同”行为和Latin1_General_CI_AS排序规则的大小写不敏感显示为不同的行。
Latin1_General_BIN 归类从何而来?看起来 sys.fulltext_system_stopwords 表有不同的排序规则,但为什么呢?
该整理来自一个不太可能的来源。让我们看看查询中的系统目录视图:
EXEC sys.sp_help N'sys.fulltext_stopwords';
Run Code Online (Sandbox Code Playgroud)
结果表明这是一个视图(如预期的那样)并且该stopword列的排序规则为Latin1_General_BIN(非预期)。但是等等,如果Latin1_General_BIN Collation 来自sys.fulltext_stopwords,那么sys.fulltext_system_stopwords另一个 Collation 又是从哪里来的呢?我们看看吧:
EXEC sys.sp_help N'sys.fulltext_system_stopwords';
Run Code Online (Sandbox Code Playgroud)
结果表明这是一个视图(如预期)并且该stopword列具有SQL_Latin1_General_CP1_CI_AS的排序规则(非预期)。
我们现在可以更深入地了解每个系统目录视图的定义:
EXEC sys.sp_helptext N'sys.fulltext_stopwords';
Run Code Online (Sandbox Code Playgroud)
返回(简化):
SELECT
fts.stopword,
FROM sys.sysftstops fts
Run Code Online (Sandbox Code Playgroud)
进而:
EXEC sys.sp_help N'sys.sysftstops';
Run Code Online (Sandbox Code Playgroud)
结果表明这是一个系统表,并且该stopword列确实具有Latin1_General_BIN的排序规则。
接下来我们可以转到另一个系统目录视图:
EXEC sys.sp_helptext N'sys.fulltext_system_stopwords';
Run Code Online (Sandbox Code Playgroud)
返回(简化):
SELECT convert(nvarchar(64), stopword) as stopword, language_id
FROM OpenRowset(TABLE FTSYSSTPWD)
Run Code Online (Sandbox Code Playgroud)
并且FTSYSSTPWD来自资源数据库,因此此时我们无能为力。
尽管如此,我们还可以做最后一件事来清楚来自资源数据库的数据的整理 - sys.fulltext_system_stopwords.stopword:
CREATE DATABASE [FullTextCollationTest] COLLATE SQL_EBCDIC277_CP1_CS_AS;
GO
USE [FullTextCollationTest];
EXEC sys.sp_help N'sys.fulltext_stopwords';
-- Collation for [stopword] column: Latin1_General_BIN (same as before)
EXEC sys.sp_help N'sys.fulltext_system_stopwords';
-- Collation for [stopword] column: SQL_EBCDIC277_CP1_CS_AS (same as DB's default Collation)
GO
USE [master];
DROP DATABASE [FullTextCollationTest];
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5259 次 |
| 最近记录: |