我的 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</td><td>France</td><td>340</td><td>470</td><td>390</td><td>293</td><td>188</td><td>38</td><td>62</td><td>71</td><td>39</td><td>15</td><td>77</td><td>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</td><td>France</td><td>534</td><td>558</td><td>420</td><td>608</td><td>413</td><td>72</td><td>71</td><td>238</td><td>48</td><td>110</td><td>44</td><td>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</td><td>United
Kingdom</td><td>1298</td><td>910</td><td>1289</td><td>1720</td><td>1165</td><td>1112</td><td>793</td><td>1045</td><td>1419</td><td>862</td><td>752</td><td>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</td><td>United
Kingdom</td><td>874</td><td>777</td><td>1389</td><td>1896</td><td>1229</td><td>916</td><td>886</td><td>1225</td><td>1360</td><td>961</td><td>770</td><td>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>
【问题讨论】:
行的<tr>
丢失,@ColumnHeader 只有一个<TR>
,其余行没有
请将 HTML 结果添加到您的帖子中(不仅仅是屏幕截图)
@AMINCHAR Html 结果现已添加。
【参考方案1】:
问题是您(obv)以错误的模式构建表格,您的 img 建议我您的 <td>
标签有问题,如果您添加 html 输出代码,我可以为您提供更多帮助
编辑:
有两个问题:
1.你关闭<p>
tag太晚了,毕竟<td>
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</td><td>France</td><td>340</td><td>470</td><td>390</td><td>293</td><td>188</td><td>38</td><td>62</td><td>71</td><td>39</td><td>15</td><td>77</td><td>17<o:p></o:p></span></p>
</td>
可能的解决方案:不要使用 <p>
标签,而是在 <tr>
标签上使用你的类
2. 在实际表格的末尾创建另一个表格
Kingdom</td><td>874</td><td>777</td><td>1389</td><td>1896</td><td>1229</td><td>916</td><td>886</td><td>1225</td><td>1360</td><td>961</td><td>770</td><td>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>
可能的解决方案:在所有行插入后关闭<table>
标签并用end
中断过程
【讨论】:
感谢您调查此问题。我已经添加了输出的 HTML 代码。以上是关于我的 SQL 存储过程中的 HTML 格式化语法无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章