Freigeben über


SQL Server-Abfrage, die eine Unicode-Spalte in eine binäre Sortierung eingibt, gibt falsche Ergebnisse zurück.

Dieser Artikel hilft Ihnen, das Problem zu beheben, das auftritt, wenn eine Anweisung eine oder OR eine IN Klausel enthält, die für eine Unicode-Spalte definiert ist und zum Eingeben der Unicode-Spalte in eine andere binäre Sortierung enthältcollate.

Ursprüngliche Produktversion: SQL Server
Ursprüngliche KB-Nummer: 3053639

Problembeschreibung

Sie haben eine Tabelle in einer SQL Server-Datenbank, in der die folgenden Bedingungen zutreffen:

  • Die Tabelle enthält eine Unicode-Spalte. Die Tabelle verfügt beispielsweise über eine nchar(5) Spalte.
  • Die Sortierung der Unicode-Spalte lautet Latin1_General_BIN.
  • Die gleiche Unicode-Spalte ist Teil eines Indexes. T-SQL-Anweisungen, die für diese Tabelle ausgeführt werden, können jedoch falsche Ergebnisse zurückgeben. Dieses Problem tritt auf, wenn die folgenden Bedingungen erfüllt sind:
    • Die T-SQL-Anweisung enthält eine oder OR eine IN Klausel, die für dieselbe Unicode-Spalte definiert ist.
    • Die T-SQL-Anweisung enthält collate den Typcast der Unicode-Spalte in eine andere binäre Sortierung.

Beispielabfrage:

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

Problemumgehung

Um dieses Problem zu umgehen, stellen Sie sicher, dass die Unicode-Spalte (Spalte3 in der Beispielabfrage im Abschnitt "Symptome ") eine der folgenden Bedingungen erfüllt:

  • Ist der Datentyp char(5) oder nvarchar(5).
  • Wird mithilfe der gleichen Sortierung Chinese_PROC_BIN definiert, für die sortate erwünscht ist (beachten Sie, dass Chinese_PROC_BIN es sich nur um ein Beispiel handelt; andere binäre Sortierungen gelten ebenfalls).
  • Ist eine andere Sortierung als Latin1_General_BIN.
  • Wird nach CI-Sortierung sortiert. Beispiel: collate Chinese_PRC_90_CI_AI IN (N'1 ', N'2 ')
  • Wird mit einer Konstante verglichen, die der Spaltenlänge entspricht. Beispiel: collate Chinese_PRC_BIN IN (N'1 ', N'2 ').
  • Ist nicht Teil des Indexes, oder ein Tabellenscan wird mithilfe des FORCESCAN Tabellenhinweiss erzwungen.
  • Funktionen wie RTRIM z. B. und LTRIM werden verwendet, um einen Tabellenscan zu erzwingen.

Weitere Informationen

Führen Sie zum Reproduzieren dieses Problems das folgende Skript aus:

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

Gilt für:

  • SQL Server 2014 Business Intelligence
  • SQL Server 2014 Developer
  • SQL Server 2014 Enterprise
  • SQL Server 2014 Enterprise Core
  • SQL Server 2014 Express
  • SQL Server 2014 Standard
  • SQL Server 2014 Web
  • SQL Server 2012 Business Intelligence
  • SQL Server 2012 Developer
  • SQL Server 2012 Enterprise
  • 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 Parallel Data Warehouse
  • 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