sql-server - 为什么相同的字符在 Windows 应用程序中呈现不同的方式?

标签 sql-server excel character-encoding character special-characters

我在 Excel 工作簿中遇到了一个 ascii 值为 63 的字符。它呈现为包含问号的实心菱形(例如,带有白色问号的黑色菱形 - �)。

如果我将其粘贴到自己的单元格中并使用 Excel CODE函数,ascii 值返回为 63。如果我在另一个单元格中键入问号,使用键盘,并使用 CODE函数,它也返回 63 的 ascii 值 - 但问号呈现“正常” - ?。

如果我检查这两个单元格上的字体,它们使用的是相同的字体(Calibri)。

如果我将这两个字符(菱形问号;普通问号)复制/粘贴到 SQL Server Management Studio 查询窗口中,它们会继续以不同的方式呈现,但 ASCII T-SQL 函数显示它们的值都是 63。

如果我将这两个字符复制/粘贴到 EditPlus 文本编辑器版本 2 中,菱形问号现在呈现为空格(除了空格之外什么都不可见)。

问题

这里发生了什么?如果不是它们的字符代码,这两个字符实际上有什么不同?

是每个字符使用的字符集吗?如何确定每个字符使用的字符集?当我尝试阅读 SQL Server 中的字符集时,它们似乎适用于每个 db/schema/table - 那么 SSMS 为了单独处理这两个字符做了什么?各个字符中必须有一些固有的东西来区分它们——而不是表级别的设置。 (无论如何,SSMS 在查询窗口中默认使用什么字符编码?即使 SSMS 为其查询窗口设置了默认字符集,显然这两个字符的呈现方式不同)。同样,当我阅读有关 Excel 字符编码的信息时,它似乎是按文档/文件定义的 - 那么 Excel 如何以不同的方式呈现相同的 ascii 字符?

这类似于 a question在 Stack Overflow 上,有人想让 SSMS 找到并替换这个神秘字符,所以我从那个问题中知道,Stack Overflow 也以不同方式呈现这两个字符 - 意思是 1. 还有另一个应用程序在字符级别以不同方式呈现它们(网络浏览器, Firefox 在我的例子中), 和 2. 你应该能够看到下面 SQL 代码中的字符:

declare @mysteryChar char(1) = '�', @knownChar char(1) = '?';
select 'mystery character', @mysteryChar union all
select 'known character', @knownChar union all
select 'mystery ascii value', cast(ascii(@mysteryChar) as varchar(16)) union all
select 'known ascii value', cast(ascii(@knownChar) as varchar(16)) union all
select 'matches knownchar', case when @mysteryChar = @knownChar then 'true' else 'false' end

如果你可以运行 T-SQL 那就太好了,代码将演示 ascii 值是相同的,最后一行显示 SQL Server 认为它们是等效字符,但即使你不能,第一行应该向你展示它们是如何呈现的在您的网络浏览器中有所不同。

PS。我找不到任何输出此菱形字符的方法,例如,使用 CHAR T-SQL 中的函数。如前所述,我在 Excel 工作簿中找到了它,并且只能将其复制/粘贴到其他应用程序中以尝试弄清楚发生了什么。

最佳答案

字符“�”和“?”是具有不同代码点的不同字符。要使用 T-SQL 查询查看字形和代码点:

SELECT 
      N'�' AS DiamondQuestionMark
    , UNICODE(N'�') AS DiamondQuestionMarkUnicodeCodePoint
    , N'?' QuestionMark
    , UNICODE(N'?') AS QuestionMarkUnicodeCodePoint;

+---------------------+-------------------------------------+--------------+------------------------------+
| DiamondQuestionMark | DiamondQuestionMarkUnicodeCodePoint | QuestionMark | QuestionMarkUnicodeCodePoint |
+---------------------+-------------------------------------+--------------+------------------------------+
| �                   |                               65533 | ?            |                           63 |
+---------------------+-------------------------------------+--------------+------------------------------+

ASCII 仅定义 0-127 码位范围内的字符。使用非 ASCII 字符的非 Unicode 文字规范,如 '�' , SQL Server 根据默认的数据库排序代码页将字符映射到 128-255 点范围内的代码点。当代码页中不存在该字符的映射时,将为该字符分配一个备用字符(例如,从代码页 1252 转换为 850 时,“Ÿ”变为“Y”)或“?”在这种情况下不存在后备字符时。

因此,因为“�”不是 ASCII 字符并且不存在于默认数据库代码页中,所以单字节文字 '�'变成 '?' .使用 Unicode 文字 N'�'和 Unicode 数据类型 ncharnvarchar避免这种代码页的肮脏。

关于sql-server - 为什么相同的字符在 Windows 应用程序中呈现不同的方式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57350803/

相关文章:

sql - 有没有一种方法可以将多个更新查询合并到一个查询中?

java - 在 Java 中创建带有国家字符的 tar 存档

来自 MySQL 数据库的 UTF-8 字符串的 PHP 输出编码问题

sql-server - 如何从 SQL Server 存储过程/触发器发送 HTTP 或 XML/RPC 请求?

c# - 使用 SQL 更新特定行

如果所需的列值重复,则 SQL 查询获取顶部记录

php - 用PHP输出UTF-8特殊字符

excel - VBA SPLIT 按不同的分隔符

arrays - 将 CSV 文件的内容加载到数组而不打开文件

excel - 通过 Excel 自动化 IE 以填写下拉列表并继续