2015-04-17 55 views
1

我需要發送一個CLR存儲過程的結果(我無法更改sproc/clr程序集)作爲HTML與電子郵件。在不使用臨時表或其他類型的持久性的情況下,是否可以捕獲和格式化存儲過程的結果集(通過電子郵件發送)?發送電子郵件中的CLR存儲過程結果

+0

爲什麼不直接從CLR內部發送電子郵件? –

+0

我不知道從C#類發送電子郵件:) – Dvintila

回答

2
USE msdb 
    EXEC sp_send_dbmail 
    @profile_name = 'MailProfile1', --you will need to create this profile in the Database Mail under Management 
    @recipients = '[email protected]', 
    @subject = 'CLR Sproc Resultset', 
    @body = 'Resultset is attached.', 
    @execute_query_database = '[DatabaseName]', 
    @query = 'exec [DatabaseName].[SchemaName].[CLRProcName]' 

試試這個,希望它應該得到你所需要的。

2

我使用Ola Hallengren's SQL Server Maintenance Solution進行數據庫備份和索引優化。我寫了幾個不同的存儲過程,在作業完成時每晚都會生成電子郵件,以便我一眼就能看到每個數據庫備份需要多長時間,重建了多少個索引和統計信息以及在哪些表格上等。

存儲我爲索引和統計編寫的程序如下。

您必須對其進行修改以適應您自己的需求和源數據,但作爲發送HTML電子郵件的模板,它應該適用於任何事情。

雖然你已經有了一個CLR存儲過程,但你必須創建一個與SP返回的模式相同的臨時表,然後執行INSERT EXEC,否則你將無法使用我的代碼。

CREATE PROCEDURE dbo.spCommandLogIndexRebuildTimePerDatabase 

    @Operator sysname 

AS 
BEGIN 
    SET NOCOUNT ON; 

    /* Debug Block 
    DECLARE @Operator sysname = 'Your Operator Name'; 
    --*/; 

    DECLARE @MaxID   int 
    ,  @xml   nvarchar(MAX) 
    ,  @body   nvarchar(MAX) 
    ,  @subj   nvarchar(255) = N'Index Optimise Results: ' + CAST(CAST(SYSDATETIME() AS date) AS nvarchar) + N' (' + @@SERVERNAME + N')' 
    ,  @span_start  nchar(31)  = N'<span style="font-weight:bold">' 
    ,  @span_end  nchar(7)  = N'</span>' 
    ,  @email   varchar(255); 

    -- drop temp table 
    BEGIN 
     IF OBJECT_ID('tempdb..#Temp') IS NOT NULL 
      DROP TABLE #Temp; 
    END 

    -- create temp table 
    BEGIN 
     CREATE TABLE #Temp 
     (
      ID     int  NOT NULL IDENTITY PRIMARY KEY 
     , [Database]   sysname 
     , [Indexes]   int 
     , [Statistics]  int 
     , [TotalDuration]  decimal(19, 3) 
     , [Time]    time 
     ); 
    END; 

    -- fill temp table 
    BEGIN 
     -- get the starting ID of the latest group of backups 
     WITH  CTEBaseData 
     AS 
     (
        SELECT  l.ID 
        ,   l.CommandType 
        ,   l.DatabaseName 
        ,   l.StartTime 
        ,   l.EndTime 
        ,   DATEDIFF(MILLISECOND, l.StartTime, l.EndTime) AS DurationMS 
        ,   ROW_NUMBER() OVER (ORDER BY l.StartTime) AS RowNum 

        FROM  dbo.CommandLog l 

        WHERE  l.CommandType IN (N'ALTER_INDEX', N'UPDATE_STATISTICS') 
     ) 

     SELECT  @MaxID = MAX(a.ID) 

     FROM  CTEBaseData a 

        LEFT JOIN CTEBaseData b 
         ON a.RowNum = b.RowNum + 1 

     WHERE  DATEDIFF(SECOND, ISNULL(b.EndTime, '2013-01-01'), a.StartTime) > 3600; 

     -- fill the temp table 
     WITH  CTEObjectTimes 
     AS 
     (
        SELECT  l.DatabaseName AS [Database] 
        ,   CASE l.CommandType WHEN N'ALTER_INDEX' THEN 1 ELSE 0 END AS [Indexes] 
        ,   CASE l.CommandType WHEN N'UPDATE_STATISTICS' THEN 1 ELSE 0 END AS [Statistics] 
        ,   DATEDIFF(MILLISECOND, l.StartTime, l.EndTime) AS [Milliseconds] 

        FROM  dbo.CommandLog l 

        WHERE  l.CommandType IN (N'ALTER_INDEX', N'UPDATE_STATISTICS') 
           AND l.ID >= @MaxID 
     ) 
     ,   CTEIndividualTotals 
     AS 
     (
        SELECT  c.[Database] 
        ,   SUM(c.[Indexes]) AS [Indexes] 
        ,   SUM(c.[Statistics]) AS [Statistics] 
        ,   SUM(c.[Milliseconds]) AS [Milliseconds] 

        FROM  CTEObjectTimes c 

        GROUP BY c.[Database] 
     ) 
     ,   CTEResult 
     AS 
     (
        SELECT  c.[Database] 
        ,   c.[Indexes] 
        ,   c.[Statistics] 
        ,   c.[Milliseconds] 
        ,   0 AS SortOrder 

        FROM  CTEIndividualTotals c 

        UNION ALL 

        SELECT  N'Total' 
        ,   SUM(c.[Indexes]) 
        ,   SUM(c.[Statistics]) 
        ,   SUM(c.Milliseconds) 
        ,   1 

        FROM  CTEIndividualTotals c 
     ) 

     INSERT  #Temp 
     (
        [Database] 
     ,   [Indexes] 
     ,   [Statistics] 
     ,   [TotalDuration] 
     ,   [Time] 
     ) 

     SELECT  c.[Database] 
     ,   c.[Indexes] 
     ,   c.[Statistics] 
     ,   CONVERT(decimal(19, 3), c.[Milliseconds]/1000.00) 
     ,   CONVERT(time, DATEADD(MILLISECOND, c.[Milliseconds], 0)) 

     FROM  CTEResult c 

     ORDER BY [SortOrder] 
     ,   [Database]; 
    END; 

    -- convert temp table to html table 
    SELECT @xml = CONVERT 
        (
         nvarchar(MAX) 
        , (
          SELECT CASE t.[Database] WHEN N'Total' THEN @span_start + t.[Database] + @span_end ELSE t.[Database] END AS [td] 
          ,  N'' 
          ,  N'right' AS [td/@align] 
          ,  CASE t.[Database] WHEN N'Total' THEN @span_start + CONVERT(nvarchar(10), t.[Indexes]) + @span_end ELSE CONVERT(nvarchar(10), t.[Indexes]) END AS [td] 
          ,  N'' 
          ,  N'right' AS [td/@align] 
          ,  CASE t.[Database] WHEN N'Total' THEN @span_start + CONVERT(nvarchar(10), t.[Statistics]) + @span_end ELSE CONVERT(nvarchar(10), t.[Statistics]) END AS [td] 
          ,  N'' 
          ,  N'right' AS [td/@align] 
          ,  CASE t.[Database] WHEN N'Total' THEN @span_start ELSE '' END 
            + LEFT(CONVERT(nvarchar(50), t.[Time]), 2) + N'h ' + SUBSTRING(CONVERT(nvarchar(50), t.[Time]), 4, 2) + N'm ' + SUBSTRING(CONVERT(nvarchar(50), t.[Time]), 7, 6) + N's' 
            + CASE t.[Database] WHEN N'Total' THEN @span_end ELSE '' END AS [td] 

          FROM #Temp t 

          FOR XML PATH('tr') 
           , ELEMENTS 
         ) 
        ); 

    -- combine the table rows from above into a complete html document 
    SELECT @body = N'<html><body><H3>Index Optimise Results for ' 
        + @@SERVERNAME 
        + N' on ' 
        + CONVERT(nvarchar(10), SYSDATETIME(), 120) 
        + N'</H3><table border = 1><tr><th> Database </th><th> Indexes </th><th> Statistics </th><th> Total Time </th></tr>' 
        + REPLACE(REPLACE(@xml, '&lt;', '<'), '&gt;', '>') 
        + N'</table></body></html>'; 

    -- get the email address of the operator 
    SELECT @email = o.email_address 
    FROM msdb.dbo.sysoperators o 
    WHERE o.name = @Operator; 

    -- just in case the operator is non-existent 
    SELECT @email = ISNULL(@email, '[email protected]'); 

    /* Debug Block 
    SELECT * 
    FROM #Temp; 

    SELECT @Body AS Body 
    ,  @email AS Email; 
    --*/; 

    -- send the email 
    EXEC msdb.dbo.sp_send_dbmail 
      @profile_name = N'Database Mail Account' 
    ,  @recipients = @email 
    ,  @subject = @subj 
    ,  @body = @body 
    ,  @body_format = 'HTML'; 
END; 
GO 

如果您對此有任何疑問,請不要猶豫,問問!

+0

非常感謝...我甚至不需要現在使用clr ...我不知道如何將結果集格式化爲HTML – Dvintila

相關問題