无法返回查询泰语数据

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

我有一个包含泰语和英语文本数据的列的表。 NVARCHAR(255)。在SSMS中,我可以查询表并轻松返回所有行。但是,如果我然后专门查询其中一个泰语结果,则不返回任何行。

SELECT TOP 1000 [Province]
,[District]
,[SubDistrict]
,[Branch ]
FROM [THDocuworldRego].[dbo].[allDistricsBranches]

返回

Province    District    SubDistrict Branch 
อุตรดิตถ์   ลับแล   ศรีพนมมาศ   Northern
Bangkok  Khlong Toei    Khlong Tan  SSS1

但是这个查询:

SELECT [Province]
      ,[District]
      ,[SubDistrict]
      ,[Branch ]
  FROM [THDocuworldRego].[dbo].[allDistricsBranches]
  where [Province] LIKE 'อุตรดิตถ์'

不返回任何行。我需要做什么来获得预期的结果。整理集是Latin1_General_CI_AS。显示并插入数据,没有错误,无法搜索。

sql-server unicode thai
2个回答
1
投票

两个问题:

  1. 传递给LIKE子句的字符串是VARCHAR,因为它没有以大写字母“N”作为前缀。例如: SELECT 'อุตรดิตถ์' AS [VARCHAR], N'อุตรดิตถ์' AS [NVARCHAR] -- ????????? อุตรดิตถ 这里发生的是当SQL Server解析查询批处理时,它需要确定所有文字/常量的确切类型和值。所以它发现12INT12.0NUMERIC等。它知道N'ดิ'NVARCHAR,这是一个包罗万象的字符集,所以它取值。但是,如前所述,'ดิ'VARCHAR,它是一个8位编码,这意味着字符集由代码页控制。对于字符串文字和变量/参数,用于VARCHAR数据的代码页是数据库的默认排序规则。如果字符串中的字符在数据库的默认排序规则使用的代码页上不可用,则它们将转换为“最佳拟合”映射,如果存在此类映射,则它们将成为默认替换字符:?。 从技术上讲,由于数据库的默认排序规则控制字符串文字(和变量),并且由于存在“泰语”的代码页(在Windows排序规则中可用),因此可以使用包含泰语字符的VARCHAR字符串(意思是:没有“N”前缀的'ดิ'会工作)。但这需要更改数据库的默认排序规则,这比简单地在字符串文字前面加上“N”要多得多。 有关此行为的深入了解,请参阅我的两部分系列: Which Collation is Used to Convert NVARCHAR to VARCHAR in a WHERE Condition? (Part A of 2: “Duck”) Which Collation is Used to Convert NVARCHAR to VARCHAR in a WHERE Condition? (Part B of 2: “Rabbit”)
  2. 您需要在两端添加通配符: N'%อุตรดิตถ์%'

最终结果如下:

WHERE [Province] LIKE N'%อุตรดิตถ์%'

编辑: 我刚刚编辑了问题,将“结果”格式化为更具可读性。现在看来,以下内容也可能有效(因为问题中的LIKE谓词中没有使用通配符):

WHERE [Province] = N'อุตรดิตถ์'

编辑2: 如果字符串文字没有前缀“N”,则字符串(即单引号内的字符串)为VARCHAR。目标数据类型是什么并不重要(例如NVARCHAR(255)列)。这里的问题是源数据的数据类型,该源是字符串文字。与.NET中的string不同,SQL Server将'string'处理为8位编码(VARCHAR;所有代码页中的ASCII值0 - 127相同,代码页确定的扩展ASCII值128 - 255,以及可能的2字节序列对于双字节字符集)和N'string'为UTF-16 Little Endian(NVARCHAR; Unicode字符集,BMP字符0 - 65535的2字节序列,代码点高于65535的两个2字节序列)。使用'string'与传入VARCHAR变量相同。例如:

DECLARE @ASCII VARCHAR(20);
SET @ASCII = N'อุตรดิตถ์';
SELECT @ASCII AS [ImplicitlyConverted]
-- ?????????

0
投票

可能是一些事情!

打印出列的值和十六进制查询字符串的拳头。

SELECT     convert(varbinary(20)Province) as stored convert(varbinary(20),'อุตรดิตถ์') as query from allDistricsBranches;

这应该可以让您对问题有所了解。我认为最可能的原因是ั,ิ,字符输入的顺序错误。它们显示为主要字母的一部分,但在内部存储为单独的字符。

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