使用 SQL Server 进行字符串的二进制比较

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

我已经看到并阅读了几个类似的问题,但我仍然没有找到我的问题的答案。我已经阅读了 MS 的各种文档,但无济于事。

有没有一种方法可以在 SQL Server 中执行区分重音、区分大小写、“填充敏感”(注意尾随空格)查询,而无需调整两个操作数? 以下脚本来自

db<>fiddle

: create table users ( id int, name varchar(255) );

insert into users (id, name) 
  values 
  (1, 'bar'),
  (2, 'bar ');
2 rows affected
在这里我希望只找到记录#2,它找到了两个:填充不敏感。

select * from users where name = 'bar ';


id12
名字
酒吧
酒吧
它也不区分大小写。

select * from users where name = 'BAR';


id12
名字
酒吧
酒吧
但对口音敏感。

select * from users where name = 'bàz';


id
名字
使用
_BIN2

似乎没有什么区别,尽管(我的理解)文档所说的(并且指定“Latin 1”感觉令人不安:我不想将我的限制限制为唯一的 ISO-8859-1片段,我想要完整的 UTF-8 覆盖)。应该什么也找不到!

select * from users
where (name collate Latin1_General_BIN2) in ('bàr', 'BAR', 'bar  ');


id12
名字
酒吧
酒吧
即使应用于两个操作数。

select * from users where (name collate Latin1_General_CS_AS) in ('bàr' collate Latin1_General_CS_AS, 'BAR' collate Latin1_General_CS_AS, 'bar ' collate Latin1_General_CS_AS);


id12
名字
酒吧
酒吧
仅在 lhs 上转换为二进制文件不起作用。

select * from users where cast(name as binary) = 'bar';


id
名字
两端的转换都有效,但我想避免这种情况(当尝试更复杂的查询时,可能会使用元组等,它的扩展性很差)

select * from users where cast(name as binary) = cast('bar' as binary);


id1
名字
酒吧
两侧的铸造也适用于
in

。但话又说回来,我想避免这种情况。

select * from users
where cast(name as binary) in 
  (cast('bàr'  as binary), 
  cast('BAR'   as binary), 
  cast('bar  ' as binary));


id
名字
那么,有什么方法可以通过仅作用于 LHS 来获得精确的二元相等测试呢?类似于 MySQL 中的
binary name = 'bar'

提前致谢!

sql-server casting collation
1个回答
0
投票
(var)binary

。由于

name
varchar(255)
我将在这里使用
varbinary(255)
。然后您可以
INDEX
该列,以便您可以进行适当的查询。但是,您仍然需要
CONVERT
您的输入值。因此,您最好使用参数,因为这样您就可以明确数据类型,因此不会最终有人传递
varchar
并导致
implicit_convert
。 Thuis 给出了一些 DDL 和 DML,如下所示:
CREATE TABLE dbo.users (id int CONSTRAINT PK_users PRIMARY KEY CLUSTERED,
                        name varchar(255));

INSERT INTO dbo.users (id,
                   name)
VALUES (1, 'bar'),
       (2, 'bar ');
GO

ALTER TABLE dbo.users ADD BinaryName AS CONVERT(varbinary(255),name);
GO
CREATE INDEX IX_users_BinaryName ON dbo.users (BinaryName) INCDUDE (name);
GO

那么对单个值的查询可能如下所示:

DECLARE @name varbinary(255) = CONVERT(varbinary(255),'bàr'); --Implicit conversion isn't allowed SELECT u.id, u.name FROM dbo.users u WHERE BinaryName = @name;

如果您需要多个值,那么最好使用表类型变量/参数和类似的东西:

DECLARE @Names table (name varbinary(255)); INSERT INTO @Names (name) SELECT CONVERT(varbinary(255),v.name) FROM (VALUES('bàr'),('BAR'),('bar '))V(name); SELECT u.id, u.name, u.BinaryName FROM dbo.users u WHERE EXISTS (SELECT 1 FROM @Names n WHERE n.name = u.BinaryName);

© www.soinside.com 2019 - 2024. All rights reserved.