为什么土耳其里拉符号₺被替换?在SQL Server 2008数据库中

时间:2014-10-07 14:22:33

标签: sql-server sql-server-2008 tsql unicode character-encoding

当我将土耳其里拉符号插入数据库中的表格时,任何想法都会被问号替换。见下图

enter image description here

2 个答案:

答案 0 :(得分:4)

这不是字体问题。这是Unicode(UTF-16)与8位代码页字符集问题(即NVARCHAR vs VARCHAR)。您尝试使用的字符不存在于执行此查询的数据库的默认排序规则所指示的特定代码页中。数据库默认排序规则使用的代码页在此处是相关的,因为您的字符串文字以大写“N”为前缀。如果是,那么该字符串将被解释为Unicode并且不会发生转换。但是,由于您传入的是非Unicode字符串,因此在解析查询时,它将被强制进入当前数据库的默认排序规则的代码页。该代码页中没有的任何字符,如果没有最适合的映射,则变为“?”。

您可以运行以下内容自行查看:

SELECT '₺';
PRINT '₺';

它在结果网格中打印和显示为?

如果要查看SQL Server认为的字符,请运行以下命令:

SELECT ASCII('₺');

它将返回:63

如果要查看ASCII值为63的字符,请运行:

SELECT CHAR(63);

它将返回:?

现在运行:

SELECT N'₺';
PRINT N'₺';

这将正确打印并显示在结果网格中。

要查看符号的真实字符值,请运行以下命令:

SELECT UNICODE(N'₺'), UNICODE('₺');

这将返回:837863

但问号不是63吗?是。这是因为 not 在字符串文字'₺'前面加上大写字母“N”告诉SQL Server它是VARCHAR,因此它会被转换为默认的未知字符。

现在,如果你要在一个DB中执行这个VARCHAR版本,该版本的Collat​​ion绑定到具有此字符的代码页,那么即使没有为字符串文字添加大写字母,它也会起作用“N”。但是,目前,我找不到SQL Server中使用的任何支持此字符的代码页。因此,它可能只是一个Unicode字符,至少就SQL Server而言。

解决此问题的方法是:

  1. 将字段的数据类型更改为NVARCHAR(我在对该字段当前为VARCHAR的问题的评论中看到)。如果该字段为VARCHAR,那么即使您在字符串上使用N前缀,该字符仍将存储为?,除非列的排序规则指定的代码页支持这个角色,但同样,我认为这可能只是一个Unicode字符。
  2. 将您的INSERT语句更改为字符串字段的前缀,其大写字母为“N”:(73, 4, N'(3) ₺')。即使您将字段更改为NVARCHAR,如果您不在字符串前加N,则SQL Server会先将字符转换为?,然后插入? 。这是因为查询在执行之前被解析,并且在DB的默认排序规则的代码页中完成解析(对于非Unicode字符串文字和变量)

答案 1 :(得分:1)

可能出于同样的原因,我的浏览器没有在这个问题的标题中显示它:它不在应用程序的字符集中(或者字体可能不支持)。

在这种情况下,我的浏览器会在框中显示一些数字(表示字符代码)。 SQL服务器正在将其转换为已知字符。

确保将其存储在支持其字符集中的字符的字段中(我认为UTF-8就足够了)