我正在使用一个旧数据库,该数据库使用不稳定的字符串值作为主键。 例如,我可能会在同一个表中找到以下主键:
aa
aA
Aa
AA
aa{Space}
AA{Space}
A{Space}A
SQL Server 中的哪种排序规则最能让我拥有区分大小写和空格的主键?
我目前正在使用 Latin_General_100_BIN2_UTF8 但这似乎对空格不敏感。
如果您想要区分大小写、重音等、和“空格”敏感值,那么
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;