SQL SERVER - 通用封装发送表格的邮件
场景:
当用户需要每天通过T-SQL检索时,需要把对应结果发邮件出去。正好用户有SQL SERVER ,可利用SQL SERVER 邮件功能进行本节省略如何配置发送邮件设置。直接讲解相关知识点
知识点
编号 | 内容 | 内容 |
1 |
select * from sys.dm_exec_describe_first_result_set (' exec t',null,0) t |
此T-SQL 可以返回 列的名称,大小等信息。 例如存储过程 T 有三列,那 第一个函数 excec t 就是对应T-SQL,通过DMV 表值函数, 可以获得列的情况 举例说明 create proc t as begin select 1 as id, 2 as tel end go select * from sys.dm_exec_describe_first_result_set (' exec t',null,0) t
|
2 |
EXEC msdb.dbo.sp_send_dbmail @profile_name='私人的', |
此存储过程是发送邮件存储过程 ,1. 第一参数"私人的”是我配置邮件服务器的个性设置名称,个性设置有发送人邮箱,显示名你等等信息。 2.@body_format = 'HTML' 即我们发送 HTML格式的代码 3.@subject=@subject 便是发送邮件主题 4.@recipients=@recipients, 收件人 5. @body=@sqlbody, HTML内容
对于上面中@recipients,@sqlbody,@recipients 都是一会用到的变量。
|
3 |
<style> |
这些元素是CSS定义,就是对表格的样式定义。 左边CSS定义就是边框为1,实线,黑色,边框间合并, 间格 5PX |
4 |
STRING_AGG |
举例说明 select STRING_AGG(id,',') from (
结果就是 a,b 此种写法解决以前要拼接 字符串的复杂,要用for xml , stuff, 并且难看。
|
5 |
+=
|
举例说明 declare @str nvarchar(max)='' select @str+=CONCAT(id,' salary: ',mount,';') from (
上面结果,会把结果集, 拼成一个大字符串,给 @str变量, 使用 += 可以把每一行,都进行拼接,有的小朋友会考虑 用游标也迭代每一行,其实不必这么麻烦用 +=就可以了。
|
6 |
exec sp_executesql @v_runsql, N'@v_content nvarchar(max) out', @v_content out |
执行一个变量中的T-SQL,并把结果返回出来 举例说明 declare @v_runsql nvarchar(max)=' select @v_content=11+443 ', exec sp_executesql @v_runsql, N'@v_content nvarchar(max) out', @v_content out select @v_content
最后结果就是 454
|
思路
1. 创建临时表把结果集写到临时表中,临时表的结构信息 把列定义字符串类型,建议 nvarchar 防止其它语言字符。列信息可以通过sys.dm_exec_describe_first_result_set 获得
2. 创建一个html 模板,包括CSS定义,和 表各占位符以便替换真正内容。
3. 把标题拼接成 表格HTML,替换占位符
4.把表格内容,变成一个格式化的字符串,替换占位符
存储过程
CREATE PROC [dbo].[USP_Notification_DateSet] ( @TSQL nvarchar(max)='select 1 as id ,2 as name', @recipients nvarchar(max)='zengxinwen@sina.com', @profile_name nvarchar(max)=N'私人的设置Profile', @subject nvarchar(max)=N'查询结果通过' ) as begin declare @v_title nvarchar(max)='', --表头 @v_selectField nvarchar(max)='' , --把所有字段都拼成一行 例如 isnull(字段1,'')+','+isnull(字段2,'') @v_runsql nvarchar(max)='' , --执行SQL 语句 @v_content nvarchar(max)='', -- 表格内容 @v_body nvarchar(max)=N' <style> table { float:left; } table, th , td { border: 1px solid black; border-collapse: collapse; padding: 5px; } .title{ background-color: #f1f1f1; } table tr { background-color: #ffffff; } table td{word-break: keep-all;white-space:nowrap;} </style> <p>大家好,</p> <p> 这是一个测试,结果如下:</p> <div> <table> @title @content </table> </div> ' --1.构建临时表 if object_id('tempdb..#dt_info') is not null drop table #dt_info CREATE TABLE #dt_info(GUID_ID_IDS int) select @v_runsql+= 'ALTER TABLE #dt_info ADD '+NAME +' NVARCHAR(MAX) ;' from sys.dm_exec_describe_first_result_set(@TSQL ,null,0) exec( @v_runsql) ALTER TABLE #dt_info DROP COLUMN GUID_ID_IDS set @v_runsql='insert into #dt_info '+ @TSQL exec( @v_runsql) --插入记录 --2.构建表的标题,以及 对应字段内容拼接到 Select查询 select @v_title= '<tr class="title" >'+ STRING_AGG('<td>'+NAME+'</td>','')+'</tr>', @v_selectField = '''<tr>'+ STRING_AGG('<td>''+ isnull('+NAME+','''')+''</td>','')+'</tr>''' from sys.dm_exec_describe_first_result_set('select * from #dt_info' ,null,0) --3.把内容输出至@v_content set @v_runsql='select @v_content+='+@v_selectField+' from #dt_info ct' exec sp_executesql @v_runsql, N'@v_content nvarchar(max) out', @v_content out --4 替换占位符 并调用发送邮件 set @v_body=replace( replace(@v_body,'@title',@v_title) ,'@content',@v_content ) EXEC msdb.dbo.sp_send_dbmail @profile_name=@profile_name, @recipients=@recipients, @subject=@subject, @body=@v_body, @body_format = 'HTML' END
演示与结果
1.存储过程演示 其中发邮件人(@recipients),和邮件个性设置(@profile_name) 请替换自己正确的。
if OBJECT_ID('usp_test') is not null drop proc usp_test go create proc usp_test as begin select name,type from sys.tables end GO exec USP_Notification_DateSet @TSQL='exec usp_test', @recipients ='zengxinwen@xxxxxx', @profile_name='xxxxx', @subject =N'执行存储过程试试'
2.T-SQL演示
exec USP_Notification_DateSet @TSQL='select 1 as id, 13 as num union all select 2,3', @recipients ='zengxinwen@xxxxxx', @profile_name='xxxxx', @subject =N'执行T-SQL试试'