SQL Server 中的“二进制”排序规则

问题描述 投票:0回答:1

我正在使用一个旧数据库,该数据库使用不稳定的字符串值作为主键。 例如,我可能会在同一个表中找到以下主键:

aa
aA
Aa
AA
aa{Space}
AA{Space}
A{Space}A

SQL Server 中的哪种排序规则最能让我拥有区分大小写和空格的主键?

我目前正在使用 Latin_General_100_BIN2_UTF8 但这似乎对空格不敏感。

sql-server collation
1个回答
0
投票

如果您想要区分大小写、重音等、“空格”敏感值,那么

varchar
是错误的数据类型。 SQL 语言的一部分(作为一个整体,我并不是专门讨论 T-SQL 方言),当字符串值具有不同数量的尾随空白字符时,应将其视为相等:
'space' = 'space ' = 'space   ' = 'space                  '
。在 SQL Server 中,如果您使用不同的排序规则,这不会改变;它适用于所有排序规则。

因此,

varchar
不会帮助您,因为
PRIMARY KEY
会将值
'space'
'space '
视为相等,因此您的约束将产生错误。

您可以使用

(var)binary
,您可以选择将其作为计算列。然后您可以在其上创建您的
PRIMARY KEY
。我将在这里使用
binary
值,它是固定宽度,因为感觉更合适。这意味着像
'abc'
这样的值将存储为
0x616263000000
之类的值,而
'abc   '
将存储为
0x616263202020

因此,您的表定义可能如下所示:

CREATE TABLE dbo.YourTable (StringID varchar(25) NOT NULL,
                            BinaryID AS CONVERT(binary(25), StringID) PERSISTED --If StringID is an nvarchar, don't forget to double the number. Has to be PERSISTED to be the PK, even though StringID isn't NULLable
                            /* Some more columns here*/
                            CONSTRAINT PK_YourTable PRIMARY KEY NONCLUSTERED (BinaryID), --You might want this clustered, but is this always ascending?
                            INDEX CI_YourTable CLUSTERED (StringID)); --I know this isn't ascending either, but giving an example

然后我们可以做一些测试插入,即使

StringID
将被视为相等(参见
SELECT
的结果),
PRIMARY KEY
不会相等,所以它们成功了:

INSERT INTO dbo.YourTable (StringID)
VALUES('abc'),
      ('abc   '),
      ('abc '),
      ('Abc '),
      ('ABc '),
      ('apples'),
      ('Apples');
GO
SELECT *
FROM dbo.YourTable;
GO

SELECT *
FROM dbo.YourTable
WHERE StringID = 'abc';
GO
--Clean up
DROP TABLE dbo.YourTable;
© www.soinside.com 2019 - 2024. All rights reserved.