本文可帮助你解决当语句包含为 Unicode 列定义的或INOR子句并包含collate将 Unicode 列类型转换为另一个二进制排序规则时发生的问题。
原始产品版本:SQL Server
原始 KB 数: 3053639
现象
SQL Server 数据库中有一个表,其中满足以下条件:
- 该表包含 Unicode 列。 例如,表有一列
nchar(5)。 - Unicode 列的排序规则为
Latin1_General_BIN. - 同一 Unicode 列是索引的一部分。 但是,针对此表运行的 T-SQL 语句可能会返回不正确的结果。 如果满足以下条件,则会出现此问题:
- T-SQL 语句包含为同一 Unicode 列定义的或
INOR子句。 - T-SQL 语句包含
collate将 Unicode 列类型化为另一个二进制排序规则。
- T-SQL 语句包含为同一 Unicode 列定义的或
示例查询:
CREATE TABLE [dbo].[Table_1]([Col1] [smallint] NOT NULL,
[Col2] [nchar](5),
[Col3] [nchar](5) COLLATE Latin1_General_BIN NOT NULL, -- Col3 , a Unicode Column with "Latin1_General_BIN" collation
CONSTRAINT [PK__Table_1] PRIMARY KEY CLUSTERED -- Primary Key on all the 3 columns
([Col1] ASC,
[Col2] ASC,
[Col3] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SELECT * FROM Table_1 WHERE Col1 = 1 AND Col2 = '1' AND Col3 COLLATE Chinese_PRC_BIN IN (N'1' ,N'2') -- This statement using "IN" and "collate" might give incorrect results.
GO
SELECT * FROM Table_1 WHERE Col1 = 1 AND Col2 = '1' AND (Col3 COLLATE Chinese_PRC_BIN = N'1' OR Col3 COLLATE Chinese_PRC_BIN = N'2') -- This statement using "OR" and "collate" might give incorrect results.
GO
解决方法
若要解决此问题,请确保 Unicode 列(“症状”部分中的示例查询中的 Col3)满足以下条件之一:
char(5)数据类型或nvarchar(5).- 通过使用所需排序规则的
Chinese_PROC_BIN相同排序规则来定义(请注意Chinese_PROC_BIN这只是一个示例;其他二进制排序规则也适用)。 - 不是排序规则
Latin1_General_BIN。 - 按 CI 排序规则进行排序。 例如:
collate Chinese_PRC_90_CI_AI IN (N'1 ', N'2 ')。 - 与与列长度匹配的常量进行比较。 例如,
collate Chinese_PRC_BIN IN (N'1 ', N'2 ')。 - 不是索引的一部分,或者表扫描是使用表提示强制进行的
FORCESCAN。 - 例如
RTRIM并LTRIM用于强制表扫描的函数。
详细信息
若要重现此问题,请运行以下脚本:
CREATE DATABASE Test_DB
GO
USE Test_DB
GO
CREATE TABLE [dbo].[Table_1]([Col1] [smallint] NOT NULL,
[Col2] [nchar](5),
[Col3] [nchar](5) COLLATE Latin1_General_BIN NOT NULL, -- Col3 , a Unicode Column with "Latin1_General_BIN" collation
CONSTRAINT [PK__Table_1] PRIMARY KEY CLUSTERED -- Primary Key on all the 3 columns
([Col1] ASC,
[Col2] ASC,
[Col3] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
-- Populate the table with a sample script as below
DECLARE @x AS INT
DECLARE @y AS INT
SET @x=1
SET @y=1
WHILE (@x<=2)
BEGIN
WHILE (@y<=1000)
BEGIN
INSERT INTO Table_1 values (@x,@y,@y)
SET @y=@y+1
END
SET @x=@x +1
END
GO
SELECT * FROM Table_1 WHERE Col1 = 1 AND Col2 = '1' AND Col3 COLLATE Chinese_PRC_BIN = N'1' -- Expected output of one row.
GO
SELECT * FROM Table_1 WHERE Col1 = 1 AND Col2 = '1' AND Col3 COLLATE Chinese_PRC_BIN IN (N'1' ,N'2') -- No rows returned when output for Col3= N'1' is expected.
GO
SELECT * FROM Table_1 WHERE Col1 = 1 AND Col2 = '1' AND (Col3 COLLATE Chinese_PRC_BIN = N'1' OR Col3 COLLATE Chinese_PRC_BIN = N'2') -- No rows returned when output for Col3= N'1' is expected.
GO
适用于
- SQL Server 2014 Business Intelligence
- SQL Server 2014 开发人员
- SQL Server 2014 Enterprise
- SQL Server 2014 Enterprise Core
- SQL Server 2014 Express
- SQL Server 2014 Standard
- SQL Server 2014 Web
- SQL Server 2012 商业智能
- SQL Server 2012 开发人员
- SQL Server 2012 企业版
- SQL Server 2012 Express
- SQL Server 2012 Standard
- SQL Server 2012 Web
- SQL Server 2012 Enterprise Core
- SQL Server 2008 R2 Datacenter
- SQL Server 2008 R2 Developer
- SQL Server 2008 R2 Enterprise
- SQL Server 2008 R2 Express
- SQL Server 2008 R2 并行数据仓库
- SQL Server 2008 R2 Standard
- SQL Server 2008 R2 Web
- SQL Server 2008 R2 Workgroup
- SQL Server 2008 Developer
- SQL Server 2008 Enterprise
- SQL Server 2008 Express
- SQL Server 2008 Standard
- SQL Server 2008 Web
- SQL Server 2008 Workgroup
- SQL Server 2005 Developer Edition
- SQL Server 2005 Enterprise Edition
- SQL Server 2005 Express Edition
- SQL Server 2005 Standard Edition
- SQL Server 2005 Standard X64 Edition
- SQL Server 2005 Workgroup Edition