sp_send_dbmail 在结果集中的所有字符之间填充 00 位

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) 分隔

NoPadCapture

Sol*_*zky 5

附件的文件编码是标准的 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。