【问题标题】:� IN SQL Server databaseØ 在 SQL Server 数据库中
【发布时间】:2017-09-14 10:27:27
【问题描述】:

在我的数据库中,我有这个字符 �。我想通过查询找到它们

Select * 
from Sometable 
where somecolumn like '%�%'

这让我没有结果。

我认为是ANSI编码

【问题讨论】:

  • 列是 varchar/char 还是 nvarchar/nchar?
  • 您使用的是什么版本的 SQL Server?
  • 不止一个字符将用 � 表示,所有这些字符在您的代码页上都没有表示。尽管您看到它们的图形表示都相同,但它们仍然是不同的字符,并且它们的比较将返回 false。
  • 列是 nvarchar
  • “ANSI 编码”是一个incredibly meaningless statement。去阅读Joel's blog on character sets,然后尽可能使用不带字节序标记的UTF-8。

标签: sql sql-server tsql


【解决方案1】:

像下面这样使用 N

 where col like N'%�%'

why do you think ,you need N prefix

以字母 N 为前缀的 Unicode 字符串常量。如果没有 N 前缀,则字符串将转换为数据库的默认代码页。此默认代码页可能无法识别某些字符。

感谢 Martin Smith,之前我只测试了一个字符并且它有效,但正如 Martin 指出的那样,它返回所有字符..

以下查询有效并仅返回预期

select * from #demo where id  like N'%�%' 
COLLATE Latin1_General_100_BIN

演示:

create table #demo
(
id nvarchar(max)
)

insert into #demo
values
(N'ﬗ'),
( N'�')

想了解更多关于unicode的信息,请看下面的链接

http://kunststube.net/encoding/

https://www.joelonsoftware.com/2003/10/08/the-absolute-minimum-every-software-developer-absolutely-positively-must-know-about-unicode-and-character-sets-no-excuses/

【讨论】:

  • 即使编辑添加了COLLATE 选项,这个答案仍然不正确,因为它现在只匹配那个单个字符,但还有其他不相同的代码点将显示有问题的角色。试试下面的查询看看:SELECT NCHAR(0xD808), CASE WHEN NCHAR(0xD808) LIKE N'%�%' COLLATE Latin1_General_100_BIN2 THEN 'YES' ELSE 'NO' END;.
【解决方案2】:

这是Unicode replacement character symbol

它可以匹配 UCS-2 编码中的 2,048 个无效代码点中的任何一个(或符号本身的单个字符 U+FFFD)。

您可以使用范围和二进制整理子句将它们全部匹配 (demo)。

WITH T(N)
AS 
(
SELECT TOP 65536 NCHAR(ROW_NUMBER() OVER (ORDER BY @@SPID))
FROM master..spt_values v1, 
     master..spt_values v2
)
SELECT N 
FROM T
WHERE N LIKE '%[' +  NCHAR(65533) + NCHAR(55296) + '-' + NCHAR(57343) + ']%' COLLATE Latin1_General_100_BIN

【讨论】:

  • 我在这里唯一要改变的是,这 2,048 个代码点并不是特别无效,它们只是需要在某些组合中使用,并且不单独代表任何东西。
  • @srutzky - 我的理解是 UCS-2 不支持代理对。
  • Martin:是的,UCS-2 没有代理对的映射,但所有的高和低代理代码点都是为此目的而保留的(在 UTF-16 中实现)。幸运的是,SQL Server 是 UTF-16(Little Endian),就像 .NET 和 Windows 一样。您可以通过执行:SELECT NCHAR(0xD83C), NCHAR(0xDF78), NCHAR(0xD83C) + NCHAR(0xDF78), NCHAR(0x01F378); 看到这一点。单独的代码点是没有意义的,但在正确的组合中它们会正确显示。如果你在一个默认排序规则以_SC结尾的数据库中,那么第4个字段将显示字符而不是NULL?。
【解决方案3】:

您可以使用ASCII 找出该字符的ascii 代码

Select ascii('�')

并使用CHAR 从该代码中检索字符并将其组合到LIKE 表达式中

Select * from Sometable
where somecolumn like '%'+CHAR(63)+'%'

注意您使用的排序规则会影响结果。它还取决于您的应用程序用于提供数据的编码(UTF-8、UNICODE 等)。还有你如何存储它 VARCHAR,或者 NVARCHAR 对你看到的内容有最后的发言权。

在这个类似的问题中还有更多here

编辑 @马克

试试这个简单的测试:

create table sometable(somecolumn nvarchar(100) not null)
GO

insert into sometable
values
 ('12345')
,('123�45')
,('12345')
GO

select * from sometable
where somecolumn like '%'+CHAR(63)+'%'
GO

这仅意味着字符被存储为“?”在这个测试中。

当您看到 � 时,表示您看到的应用不确定要打印什么。

这也意味着 OP 可能需要使用查询找出 char 是什么。 另请注意,这意味着像 ��� 这样输出的字符串可以由 3 个不同的字符组成。

CHAR(63) 只是一个例子,但你是对的,ASCII table 中的这将是一个标准的询问。

编辑 @桥

现在没有时间深入研究它,但下面的测试不起作用

Select ascii('�'), CHAR(ascii('�')), UNICODE(N'�'), CHAR(UNICODE(N'�'))
GO

create table sometable(somecolumn nvarchar(100) not null)
GO

insert into sometable
values
 ('12345')
,('123�45')
,('12345')
,('12'+NCHAR(UNICODE(N'�'))+'345')
GO

select * from sometable
where somecolumn like '%'+CHAR(63)+'%'

select * from sometable
where somecolumn like '%'+NCHAR(UNICODE(N'�'))+'%'

GO

【讨论】:

  • char(63)?,而不是
  • 此字符超出 ASCII 范围 - 您需要改用 UNICODE。查看运行结果:Select ascii('�'), CHAR(ascii('�')), UNICODE(N'�'), NCHAR(UNICODE(N'�'))
猜你喜欢
  • 1970-01-01
  • 2021-05-14
  • 2015-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-09
  • 2013-09-10
相关资源
最近更新 更多