1 sql-server t-sql database-mail encoding unicode
我在每晚触发的 SQL 代理作业中使用 sp_send_dbmail。该作业查询我们的数据库并检查产品价格更新,如果有,它将通过电子邮件作为附件发送给我们的电子商务供应商。他们有一些自动流程,他们会更新我们的电子商务平台,但是他们的自动流程无法处理 sp_send_dbmail 提供的文件。sp_send_dbmail 似乎在结果集中的所有字符之间放置了空字符。
查看在十六进制编辑器中打开 csv 的结果:
通过文本编辑器查看我看到的预期:
sp_send_dbmail 在这里查询:
SET @FileName = 'Update_' + CONVERT(VARCHAR(12),GETDATE),105) '.csv'
SET @Query = 'Some Query'
EXEC msdb.dbo.sp_send_dbmail
@recipients = 'me@domain.com'
@query = @Query
@attach_query_result_as_file = 1
@query_attachment_filename = @FileName
@query_result_separator = ','
@query_result_no_padding = 1
END
Run Code Online (Sandbox Code Playgroud)
这里发生了什么?
****编辑补充说明****
使用 Microsoft SQL Server 2008 R2 排序规则为 Latin1_General_CI_AS
离开 no_padding 会在每个返回的字段中留下几个尾随空格。每个空格 (20) 由空值 (00) 分隔
附件的文件编码是标准的 UTF-16 Little Endian (LE)——各种 Unicode 编码之一。第一个图像中显示的前两个字节是FF FE
. 这些是字节顺序标记 (BOM),它是文件编码的明确指示。您可以在链接的维基百科页面上的图表中看到FF FE
指示 UTF-16 Little Endian 的编码。
UTF-16 每个“字符”使用 2 或 4 个字节,因此00
空字节实际上只是每个字符的一半。并且,因为它是 Little Endian 而不是 Big Endian,所以每对中的字节被交换。意思是,00
顶部图像中突出显示的与前面的50
(大写的P
)配对。但是这对50 00
只是 Little Endian for 00 50
,即 Unicode 代码点U+0050(该页面底部有一个图表,显示了编码变化)。
如果您在任何通过 BOM 自动检测文件编码的编辑器中打开该文件,它就会知道它是一个 UTF-16 LE 编码的文件并正确显示它,正如您所期望的那样。只需在 Notepad++ 之类的东西中尝试一下。
我要做的第一件事是联系供应商和/或检查文档以查看电子商务平台是否已经拥有处理 UTF-16 LE 编码文件(在 Microsoft 领域也称为“Unicode”)的方法,或者如果他们可以做一个小的改变来处理 Unicode 文件。如果他们都没有以某种方式处理这个问题,并且如果还没有能力就不会这样做,我会感到惊讶。鉴于这个世界正朝着更多的国际化而不是更少的方向发展,您不可能是唯一需要传入 Unicode 文件的客户端。此外,如果您的数据中自然包含不适合单个代码页的字符,则将文件转换为 ASCII 扩展可能会导致数据丢失。
我要做的最后一件事是更新sp_send_dbmail
. 我并不是说永远不要这样做,但在大多数情况下,这是不必要的。如果有的话,最好在发送后转换附件的编码(这可能需要由电子邮件的收件人完成)。有意转换将允许指定正确的编码,无论是使用许多可用代码页之一的 UTF-8 还是扩展 ASCII。