我的 SQL 存储过程中的 HTML 格式化语法无法正常工作

Posted

技术标签:

【中文标题】我的 SQL 存储过程中的 HTML 格式化语法无法正常工作【英文标题】:HTML formatting syntax in my SQL Stored Procedure not working properly 【发布时间】:2018-02-20 08:46:46 【问题描述】:

我正在使用 SQL Server 2012,并且我有一个 存储过程,它针对 View 运行,并以 html 格式通过电子邮件发送该 View 的输出格式。

这是存储过程

USE master
GO

IF EXISTS (   SELECT *
          FROM   sys.objects
          WHERE  objects.object_id = OBJECT_ID(
                                         N'[dbo].[sp_GenerateHTMLTableResults]')
                 AND objects.type IN (N'P', N'PC'))
DROP PROCEDURE [dbo].[sp_GenerateHTMLTableResults]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

IF NOT EXISTS (   SELECT *
              FROM   sys.objects
              WHERE  objects.object_id = OBJECT_ID(
                                             N'[dbo].  [sp_GenerateHTMLTableResults]')
                     AND objects.type IN (N'P', N'PC'))
BEGIN
    EXEC sys.sp_executesql @statement = N'CREATE PROCEDURE [dbo].[sp_GenerateHTMLTableResults] AS'
END
GO

ALTER PROCEDURE [dbo].[sp_GenerateHTMLTableResults]
(
    @ResultsTableName NVARCHAR(100) ,
    @GeneratedHTML NVARCHAR(MAX) OUTPUT
)
AS
  BEGIN
    DECLARE @BaseSQL NVARCHAR(MAX)
    DECLARE @SQL NVARCHAR(MAX)
    DECLARE @ColumnHeader NVARCHAR(MAX) = ''
    DECLARE @TableResults NVARCHAR(MAX) = ''
    DECLARE @ParmDefinition NVARCHAR(MAX)
    DECLARE @BodyHTML NVARCHAR(MAX)
    DECLARE @TableColumns TABLE
        (
            ColumnName NVARCHAR(MAX)
        )

    SET @BaseSQL = 'SELECT TN.N.value(''local-name(.)'', ''sysname'') AS ColumnName FROM (SELECT TV.* FROM ( SELECT 1 ) AS D(N) OUTER APPLY (SELECT TOP ( 0 ) * FROM '
                   + @ResultsTableName
                   + ' ) AS TV FOR XML PATH(''''), ELEMENTS XSINIL, TYPE ) AS TX(X) CROSS APPLY TX.X.nodes(''*'') AS TN(N)'

    INSERT INTO @TableColumns ( ColumnName )
    EXECUTE sys.sp_executesql @BaseSQL

    SET @SQL = ' SELECT @Columns = isnull(@Columns,'''') + ''<th>'' +ColumnName + ''</th>'' FROM ('
               + @BaseSQL + ') a'

    SET @ParmDefinition = N'@Columns nvarchar(max) OUTPUT';

    EXECUTE sys.sp_executesql @SQL ,
                              @ParmDefinition ,
                              @Columns = @ColumnHeader OUTPUT;

    SET @ColumnHeader = '<table cellpadding="2" cellspacing="2" border="1" style="font-family: Arial; font-size: 8pt"><TR>'
                        + @ColumnHeader + '</TR>'

    SET @SQL = 'SELECT @BodyHTML = CAST((SELECT td = '

    SELECT @SQL = @SQL + 'CAST(' + tc.ColumnName + ' as nvarchar(max)) '
                  + '+''</td><td>''+'
    FROM   @TableColumns AS tc

    SET @SQL = LEFT(@SQL, LEN(@SQL) - 13) + ' FROM ( SELECT * FROM '
               + @ResultsTableName
               + ' ) AS d FOR XML PATH(''tr''), TYPE ) AS VARCHAR(MAX))'

    SET @ParmDefinition = N'@BodyHTML nvarchar(max) OUTPUT';

    EXECUTE sys.sp_executesql @SQL ,
                              @ParmDefinition ,
                              @BodyHTML = @BodyHTML OUTPUT;

    SET @GeneratedHTML = @ColumnHeader
                         + REPLACE(
                               REPLACE(@BodyHTML, '<', '<') ,
                               '>' ,
                               '>') + '<table>'
END


GO

  EXEC sys.sp_MS_marksystemobject sp_GenerateHTMLTableResults

GO

然后我设置了一个每天执行上述存储过程的 SQL 作业。

一切正常,除了电子邮件中的 HTML 输出损坏(见下图)。

我该如何解决这个问题?

添加邮件输出的 HTML 代码:

<table class=MsoNormalTable border=1 cellpadding=0 style='mso-cellspacing:1.2pt;
 mso-yfti-tbllook:1184;mso-padding-alt:1.2pt 1.2pt 1.2pt 1.2pt'>
 <tr style='mso-yfti-irow:0;mso-yfti-firstrow:yes'>
  <td style='padding:1.2pt 1.2pt 1.2pt 1.2pt'>
  <p class=MsoNormal align=center style='text-align:center'><b><span
  style='font-size:8.0pt;font-family:"Arial",sans-serif'>StayYear<o:p></o:p></span></b></p>
  </td>
  <td style='padding:1.2pt 1.2pt 1.2pt 1.2pt'>
  <p class=MsoNormal align=center style='text-align:center'><b><span
  style='font-size:8.0pt;font-family:"Arial",sans-serif'>Market<o:p></o:p></span></b></p>
  </td>
  <td style='padding:1.2pt 1.2pt 1.2pt 1.2pt'>
  <p class=MsoNormal align=center style='text-align:center'><b><span
  style='font-size:8.0pt;font-family:"Arial",sans-serif'>Jan<o:p></o:p></span></b></p>
  </td>
  <td style='padding:1.2pt 1.2pt 1.2pt 1.2pt'>
  <p class=MsoNormal align=center style='text-align:center'><b><span
  style='font-size:8.0pt;font-family:"Arial",sans-serif'>Feb<o:p></o:p></span></b></p>
  </td>
  <td style='padding:1.2pt 1.2pt 1.2pt 1.2pt'>
  <p class=MsoNormal align=center style='text-align:center'><b><span
  style='font-size:8.0pt;font-family:"Arial",sans-serif'>Mar<o:p></o:p></span></b></p>
  </td>
  <td style='padding:1.2pt 1.2pt 1.2pt 1.2pt'>
  <p class=MsoNormal align=center style='text-align:center'><b><span
  style='font-size:8.0pt;font-family:"Arial",sans-serif'>Apr<o:p></o:p></span></b></p>
  </td>
  <td style='padding:1.2pt 1.2pt 1.2pt 1.2pt'>
  <p class=MsoNormal align=center style='text-align:center'><b><span
  style='font-size:8.0pt;font-family:"Arial",sans-serif'>May<o:p></o:p></span></b></p>
  </td>
  <td style='padding:1.2pt 1.2pt 1.2pt 1.2pt'>
  <p class=MsoNormal align=center style='text-align:center'><b><span
  style='font-size:8.0pt;font-family:"Arial",sans-serif'>Jun<o:p></o:p></span></b></p>
  </td>
  <td style='padding:1.2pt 1.2pt 1.2pt 1.2pt'>
  <p class=MsoNormal align=center style='text-align:center'><b><span
  style='font-size:8.0pt;font-family:"Arial",sans-serif'>Jul<o:p></o:p></span></b></p>
  </td>
  <td style='padding:1.2pt 1.2pt 1.2pt 1.2pt'>
  <p class=MsoNormal align=center style='text-align:center'><b><span
  style='font-size:8.0pt;font-family:"Arial",sans-serif'>Aug<o:p></o:p></span></b></p>
  </td>
  <td style='padding:1.2pt 1.2pt 1.2pt 1.2pt'>
  <p class=MsoNormal align=center style='text-align:center'><b><span
  style='font-size:8.0pt;font-family:"Arial",sans-serif'>Sep<o:p></o:p></span></b></p>
  </td>
  <td style='padding:1.2pt 1.2pt 1.2pt 1.2pt'>
  <p class=MsoNormal align=center style='text-align:center'><b><span
  style='font-size:8.0pt;font-family:"Arial",sans-serif'>Oct<o:p></o:p></span></b></p>
  </td>
  <td style='padding:1.2pt 1.2pt 1.2pt 1.2pt'>
  <p class=MsoNormal align=center style='text-align:center'><b><span
  style='font-size:8.0pt;font-family:"Arial",sans-serif'>Nov<o:p></o:p></span></b></p>
  </td>
  <td style='padding:1.2pt 1.2pt 1.2pt 1.2pt'>
  <p class=MsoNormal align=center style='text-align:center'><b><span
  style='font-size:8.0pt;font-family:"Arial",sans-serif'>Dec<o:p></o:p></span></b></p>
  </td>
 </tr>
 <tr style='mso-yfti-irow:1'>
  <td style='padding:1.2pt 1.2pt 1.2pt 1.2pt'>
  <p class=MsoNormal><span style='font-size:8.0pt;font-family:"Arial",sans-serif'>2017&lt;/td&gt;&lt;td&gt;France&lt;/td&gt;&lt;td&gt;340&lt;/td&gt;&lt;td&gt;470&lt;/td&gt;&lt;td&gt;390&lt;/td&gt;&lt;td&gt;293&lt;/td&gt;&lt;td&gt;188&lt;/td&gt;&lt;td&gt;38&lt;/td&gt;&lt;td&gt;62&lt;/td&gt;&lt;td&gt;71&lt;/td&gt;&lt;td&gt;39&lt;/td&gt;&lt;td&gt;15&lt;/td&gt;&lt;td&gt;77&lt;/td&gt;&lt;td&gt;17<o:p></o:p></span></p>
  </td>
  <td style='border:none;padding:1.2pt 1.2pt 1.2pt 1.2pt'></td>
  <td style='border:none;padding:1.2pt 1.2pt 1.2pt 1.2pt'></td>
  <td style='border:none;padding:1.2pt 1.2pt 1.2pt 1.2pt'></td>
  <td style='border:none;padding:1.2pt 1.2pt 1.2pt 1.2pt'></td>
  <td style='border:none;padding:1.2pt 1.2pt 1.2pt 1.2pt'></td>
  <td style='border:none;padding:1.2pt 1.2pt 1.2pt 1.2pt'></td>
  <td style='border:none;padding:1.2pt 1.2pt 1.2pt 1.2pt'></td>
  <td style='border:none;padding:1.2pt 1.2pt 1.2pt 1.2pt'></td>
  <td style='border:none;padding:1.2pt 1.2pt 1.2pt 1.2pt'></td>
  <td style='border:none;padding:1.2pt 1.2pt 1.2pt 1.2pt'></td>
  <td style='border:none;padding:1.2pt 1.2pt 1.2pt 1.2pt'></td>
  <td style='border:none;padding:1.2pt 1.2pt 1.2pt 1.2pt'></td>
  <td style='border:none;padding:1.2pt 1.2pt 1.2pt 1.2pt'></td>
 </tr>
 <tr style='mso-yfti-irow:2'>
  <td style='padding:1.2pt 1.2pt 1.2pt 1.2pt'>
  <p class=MsoNormal><span style='font-size:8.0pt;font-family:"Arial",sans-serif'>2018&lt;/td&gt;&lt;td&gt;France&lt;/td&gt;&lt;td&gt;534&lt;/td&gt;&lt;td&gt;558&lt;/td&gt;&lt;td&gt;420&lt;/td&gt;&lt;td&gt;608&lt;/td&gt;&lt;td&gt;413&lt;/td&gt;&lt;td&gt;72&lt;/td&gt;&lt;td&gt;71&lt;/td&gt;&lt;td&gt;238&lt;/td&gt;&lt;td&gt;48&lt;/td&gt;&lt;td&gt;110&lt;/td&gt;&lt;td&gt;44&lt;/td&gt;&lt;td&gt;76<o:p></o:p></span></p>
  </td>
  <td style='border:none;padding:1.2pt 1.2pt 1.2pt 1.2pt'></td>
  <td style='border:none;padding:1.2pt 1.2pt 1.2pt 1.2pt'></td>
  <td style='border:none;padding:1.2pt 1.2pt 1.2pt 1.2pt'></td>
  <td style='border:none;padding:1.2pt 1.2pt 1.2pt 1.2pt'></td>
  <td style='border:none;padding:1.2pt 1.2pt 1.2pt 1.2pt'></td>
  <td style='border:none;padding:1.2pt 1.2pt 1.2pt 1.2pt'></td>
  <td style='border:none;padding:1.2pt 1.2pt 1.2pt 1.2pt'></td>
  <td style='border:none;padding:1.2pt 1.2pt 1.2pt 1.2pt'></td>
  <td style='border:none;padding:1.2pt 1.2pt 1.2pt 1.2pt'></td>
  <td style='border:none;padding:1.2pt 1.2pt 1.2pt 1.2pt'></td>
  <td style='border:none;padding:1.2pt 1.2pt 1.2pt 1.2pt'></td>
  <td style='border:none;padding:1.2pt 1.2pt 1.2pt 1.2pt'></td>
  <td style='border:none;padding:1.2pt 1.2pt 1.2pt 1.2pt'></td>
 </tr>
 <tr style='mso-yfti-irow:3'>
  <td style='padding:1.2pt 1.2pt 1.2pt 1.2pt'>
  <p class=MsoNormal><span style='font-size:8.0pt;font-family:"Arial",sans-serif'>2017&lt;/td&gt;&lt;td&gt;United
  Kingdom&lt;/td&gt;&lt;td&gt;1298&lt;/td&gt;&lt;td&gt;910&lt;/td&gt;&lt;td&gt;1289&lt;/td&gt;&lt;td&gt;1720&lt;/td&gt;&lt;td&gt;1165&lt;/td&gt;&lt;td&gt;1112&lt;/td&gt;&lt;td&gt;793&lt;/td&gt;&lt;td&gt;1045&lt;/td&gt;&lt;td&gt;1419&lt;/td&gt;&lt;td&gt;862&lt;/td&gt;&lt;td&gt;752&lt;/td&gt;&lt;td&gt;226<o:p></o:p></span></p>
  </td>
  <td style='border:none;padding:1.2pt 1.2pt 1.2pt 1.2pt'></td>
  <td style='border:none;padding:1.2pt 1.2pt 1.2pt 1.2pt'></td>
  <td style='border:none;padding:1.2pt 1.2pt 1.2pt 1.2pt'></td>
  <td style='border:none;padding:1.2pt 1.2pt 1.2pt 1.2pt'></td>
  <td style='border:none;padding:1.2pt 1.2pt 1.2pt 1.2pt'></td>
  <td style='border:none;padding:1.2pt 1.2pt 1.2pt 1.2pt'></td>
  <td style='border:none;padding:1.2pt 1.2pt 1.2pt 1.2pt'></td>
  <td style='border:none;padding:1.2pt 1.2pt 1.2pt 1.2pt'></td>
  <td style='border:none;padding:1.2pt 1.2pt 1.2pt 1.2pt'></td>
  <td style='border:none;padding:1.2pt 1.2pt 1.2pt 1.2pt'></td>
  <td style='border:none;padding:1.2pt 1.2pt 1.2pt 1.2pt'></td>
  <td style='border:none;padding:1.2pt 1.2pt 1.2pt 1.2pt'></td>
  <td style='border:none;padding:1.2pt 1.2pt 1.2pt 1.2pt'></td>
 </tr>
 <tr style='mso-yfti-irow:4;mso-yfti-lastrow:yes'>
  <td style='padding:1.2pt 1.2pt 1.2pt 1.2pt'>
  <p class=MsoNormal><span style='font-size:8.0pt;font-family:"Arial",sans-serif'>2018&lt;/td&gt;&lt;td&gt;United
  Kingdom&lt;/td&gt;&lt;td&gt;874&lt;/td&gt;&lt;td&gt;777&lt;/td&gt;&lt;td&gt;1389&lt;/td&gt;&lt;td&gt;1896&lt;/td&gt;&lt;td&gt;1229&lt;/td&gt;&lt;td&gt;916&lt;/td&gt;&lt;td&gt;886&lt;/td&gt;&lt;td&gt;1225&lt;/td&gt;&lt;td&gt;1360&lt;/td&gt;&lt;td&gt;961&lt;/td&gt;&lt;td&gt;770&lt;/td&gt;&lt;td&gt;328<o:p></o:p></span></p>
  </td>
  <td style='border:none;padding:1.2pt 1.2pt 1.2pt 1.2pt'>
  <table class=MsoNormalTable border=0 cellspacing=3 cellpadding=0
   style='mso-cellspacing:1.5pt;mso-yfti-tbllook:1184'>
   <tr style='mso-yfti-irow:0;mso-yfti-firstrow:yes;mso-yfti-lastrow:yes'>
    <td style='padding:.75pt .75pt .75pt .75pt'></td>
   </tr>
  </table>

【问题讨论】:

行的&lt;tr&gt; 丢失,@ColumnHeader 只有一个&lt;TR&gt;,其余行没有 请将 HTML 结果添加到您的帖子中(不仅仅是屏幕截图) @AMINCHAR Html 结果现已添加。 【参考方案1】:

问题是您(obv)以错误的模式构建表格,您的 img 建议我您的 &lt;td&gt; 标签有问题,如果您添加 html 输出代码,我可以为您提供更多帮助

编辑:

有两个问题: 1.你关闭&lt;p&gt;tag太晚了,毕竟&lt;td&gt;tags

 <td style='padding:1.2pt 1.2pt 1.2pt 1.2pt'>
  <p class=MsoNormal><span style='font-size:8.0pt;font-family:"Arial",sans-serif'>2017&lt;/td&gt;&lt;td&gt;France&lt;/td&gt;&lt;td&gt;340&lt;/td&gt;&lt;td&gt;470&lt;/td&gt;&lt;td&gt;390&lt;/td&gt;&lt;td&gt;293&lt;/td&gt;&lt;td&gt;188&lt;/td&gt;&lt;td&gt;38&lt;/td&gt;&lt;td&gt;62&lt;/td&gt;&lt;td&gt;71&lt;/td&gt;&lt;td&gt;39&lt;/td&gt;&lt;td&gt;15&lt;/td&gt;&lt;td&gt;77&lt;/td&gt;&lt;td&gt;17<o:p></o:p></span></p>
  </td> 

可能的解决方案:不要使用 &lt;p&gt; 标签,而是在 &lt;tr&gt; 标签上使用你的类 2. 在实际表格的末尾创建另一个表格

Kingdom&lt;/td&gt;&lt;td&gt;874&lt;/td&gt;&lt;td&gt;777&lt;/td&gt;&lt;td&gt;1389&lt;/td&gt;&lt;td&gt;1896&lt;/td&gt;&lt;td&gt;1229&lt;/td&gt;&lt;td&gt;916&lt;/td&gt;&lt;td&gt;886&lt;/td&gt;&lt;td&gt;1225&lt;/td&gt;&lt;td&gt;1360&lt;/td&gt;&lt;td&gt;961&lt;/td&gt;&lt;td&gt;770&lt;/td&gt;&lt;td&gt;328<o:p></o:p></span></p>
  </td>
  <td style='border:none;padding:1.2pt 1.2pt 1.2pt 1.2pt'>
  <table class=MsoNormalTable border=0 cellspacing=3 cellpadding=0
   style='mso-cellspacing:1.5pt;mso-yfti-tbllook:1184'>
   <tr style='mso-yfti-irow:0;mso-yfti-firstrow:yes;mso-yfti-lastrow:yes'>
    <td style='padding:.75pt .75pt .75pt .75pt'></td>
   </tr>
  </table>

可能的解决方案:在所有行插入后关闭&lt;table&gt;标签并用end中断过程

【讨论】:

感谢您调查此问题。我已经添加了输出的 HTML 代码。

以上是关于我的 SQL 存储过程中的 HTML 格式化语法无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章

存储过程具体过程以及sql数据库调用和程序代码调用

在SQL中存储过程的一般语法是啥?

存储过程和函数

SQL中模式创建的语法?

Liquibase:MySQL 存储过程中的 SQL 语法错误

我可以将存储过程的结果放入 SQL 中另一个存储过程中的游标中吗