AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 83776
Accepted
Heisenberg
Heisenberg
Asked: 2014-11-28 00:30:16 +0800 CST2014-11-28 00:30:16 +0800 CST 2014-11-28 00:30:16 +0800 CST

Precisa enviar um email HTML formatado via Database Mail no Sql Server 2008 R2

  • 772

Meu requisito é criar o e-mail automatizado como ( Um e-mail HTML formatado via Database Mail) O requisito básico foi concluído onde quando o Job é acionado ele insere os dados em uma Tabela e essa informação foi agendada para ser enviada como um E-mail, mas agora o cliente solicitou neste formato.

Formato atual que fiz

 PO Date:2014-11-26 PO ID:PO1 SAP Ref:0001106102 GRN:1067 DealerID:045 Dealer Name:ABC(Pvt)Ltd. 2 Status:New

Formato solicitado pelo cliente em formato de tabela

PO Date |PO ID| SAP Ref| GRN|DealerID|Dealer Name|Status

Esta é a consulta SQL que utilizo para inserir os dados no Email_Table(_ERROR_MAIL) e isso precisa ser cobiçado de acordo com o requisito

IF EXISTS (SELECT * FROM sysobjects WHERE type = 'P' AND name = 'ImpCancelledGRN')
BEGIN
    DROP PROCEDURE [dbo].[ImpCancelledGRN]
END
GO


CREATE PROCEDURE [dbo].[ImpCancelledGRN] 
WITH ENCRYPTION
AS

SET NOCOUNT ON
BEGIN
BEGIN TRY
    -- Begin transaction
    BEGIN TRAN

            INSERT INTO _ERROR_MAIL(Recipients, Subject, CreationDate, IsNew, LastModifiedBy, Body)
            SELECT '[email protected]', 'SAP CANCELLED GRN', GETDATE(), 1, 'sapws',
                'PO Date:' + CONVERT(VARCHAR(10),P.Date,120) + 
                ' PO ID:' + P.ID + 
                ' SAP Ref:' + P.ID2 + 
                ' GRN:' + G.ID + 
                ' Dealer ID:' + D.ID + 
                ' Dealer Name:' + D.Name + 
                ' Status:' + CASE WHEN G.SubmittedDate IS NULL THEN 'New' ELSE 'Dealer Submitted' END
            FROM I_CancelledGRN I
                INNER JOIN TxnGRN G ON G.ID = I.ID
                INNER JOIN Distributor D ON D.UID = G.DistributorUID
                INNER JOIN POTxn P ON P.SiteUID = G.POTxn_SiteUID AND P.UID = G.POTxnUID
            WHERE IsCancelled IS NULL;

            UPDATE TxnGRN 
            SET ExpiryDate = GETDATE() 
                , SAPCancellationDate = I.Date
                , SAPCancelledBy = 'SAP'
                , IsCancelled = 1
            FROM I_CancelledGRN I
                INNER JOIN TxnGRN G ON G.ID = I.ID
            WHERE IsCancelled IS NULL;

    -- Commit transaction
    COMMIT TRAN 

END TRY
BEGIN CATCH
    -- Get error message, severity and satus information
    DECLARE @ErrorMessage NVARCHAR(4000), @ErrorSeverity INT, @ErrorState INT;
    SELECT @ErrorMessage = ERROR_MESSAGE(), @ErrorSeverity = ERROR_SEVERITY(),    @ErrorState = ERROR_STATE();
    -- Rollback transaction
    ROLLBACK TRAN;
    -- Log error message details
    INSERT INTO _ERROR_LOG(Module, SubModule, Text, Date)
    VALUES('SAP', '[ImpCancelledGRN]', @ErrorMessage, GETDATE());
    -- Raise error
    RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState);
END CATCH
RETURN 0;   
END
SET NOCOUNT OFF
GO     
sql-server sql-server-2008-r2
  • 2 2 respostas
  • 90332 Views

2 respostas

  • Voted
  1. Best Answer
    AA.SC
    2014-11-28T01:49:42+08:002014-11-28T01:49:42+08:00

    Aqui, como você pode criar parte do corpo HTML do seu e-mail.

    Passo 1:

     DECLARE @Body NVARCHAR(MAX),
        @TableHead VARCHAR(1000),
        @TableTail VARCHAR(1000)
    
    
    
    SET @TableTail = '</table></body></html>' ;
    SET @TableHead = '<html><head>' + '<style>'
        + 'td {border: solid black;border-width: 1px;padding-left:5px;padding-right:5px;padding-top:1px;padding-bottom:1px;font: 11px arial} '
        + '</style>' + '</head>' + '<body>' + 'Report generated on : '
        + CONVERT(VARCHAR(50), GETDATE(), 106) 
        + ' <br> <table cellpadding=0 cellspacing=0 border=0>' 
        + '<tr> <td bgcolor=#E6E6FA><b>PO Date</b></td>'
        + '<td bgcolor=#E6E6FA><b>PO ID</b></td>'
        + '<td bgcolor=#E6E6FA><b>SAP Ref</b></td>'
        + '<td bgcolor=#E6E6FA><b>GRN</b></td>'
        + '<td bgcolor=#E6E6FA><b>DealerID</b></td>'
        + '<td bgcolor=#E6E6FA><b>Dealer Name</b></td>'
        + '<td bgcolor=#E6E6FA><b>Status</b></td></tr>' ;
    
    SET @Body = ( SELECT    td = CONVERT(VARCHAR(10), P.Date, 120), '',
                            td = P.ID, '',
                            td = P.ID2, '',
                            td = G.ID, '',
                            td = D.ID,'',
                            td = D.Name,'',
                            td = CASE WHEN G.SubmittedDate IS NULL THEN 'New'
                                      ELSE 'Dealer Submitted'
                                 END, ''
                  FROM      I_CancelledGRN I
                            INNER JOIN TxnGRN G ON G.ID = I.ID
                            INNER JOIN Distributor D ON D.UID = G.DistributorUID
                            INNER JOIN POTxn P ON P.SiteUID = G.POTxn_SiteUID
                                                  AND P.UID = G.POTxnUID
                  WHERE IsCancelled IS NULL
                FOR   XML RAW('tr'),
                      ELEMENTS
                )
    
    
    
    SELECT  @Body = @TableHead + ISNULL(@Body, '') + @TableTail
    

    Etapa 2: criar perfil de e-mail do banco de dados

    Etapa 3: enviar e-mail

    EXEC sp_send_dbmail 
      @profile_name='DatabaseEmailProfile',
      @copy_recipients ='[email protected]',
      @recipients='[email protected]',
      @subject='Query Result',
      @body=@Body ,
      @body_format = 'HTML' ;
    
    • 15
  2. Leigh Haynes
    2015-05-05T12:08:23+08:002015-05-05T12:08:23+08:00

    Meus usuários estão encontrando a solução "XML PATH" e tentando usá-la, mas eles não são programadores e ficam confusos. Em vez de tentar ajudá-los a aprender a usar XML PATH, criei um procedimento que recebe o nome de uma tabela e retorna uma string contendo a marcação HTML para exibir a tabela como uma tabela HTML. Minha solução deriva dinamicamente os nomes das colunas da tabela HTML da fonte de dados.

    Exemplo de uso do procedimento HtmlTable

    CREATE table ##foo (bar1 int, bar2 varchar(20), bar3 datetime)
    INSERT into ##foo values (1, 'Abcdef', getdate())
    INSERT into ##foo values (2, 'Ghijkl', '05/05/15')
    DECLARE @tableHtml varchar(max)
    EXEC dbo.HtmlTable
        '##foo',
        @tableHtml output
    PRINT @tableHtml    
    

    A variável @tableHtml contém apenas marcação para uma tabela HTML, que é apropriada para inclusão em um corpo de email. Para visualizar sozinho, você precisa envolver a saída com as tags html, head e body.

    Saída do procedimento HtmlTable

    conteúdo de @tableHtml

    Código para o procedimento HtmlTable

    /*
    Author: Leigh Haynes
    Date: February 2015
    Notes: Takes a table name as string parameter and returns a string that contains HTML markup to display the table contents as an HTML table.
    
    The input table should be sorted before invoking HtmlTable.
    
    */
    
    CREATE PROCEDURE [dbo].[HtmlTable]
        @data_source varchar (100) = NULL,
        @tableHTML varchar(max) OUTPUT
    AS
    
    BEGIN    
    
    SET NOCOUNT ON;
    
    DECLARE 
        @db varchar(50), 
        @table varchar(100), 
        @cmd varchar(400), 
        @rcd_cnt int,
        @sql nvarchar(1000);
    
    --use procedure DataSourceCheck to see if @data_source is valid
    EXEC dbo.DataSourceCheck @data_source, @db output, @table output;
    
    IF @db is NULL --if the data source is not good, @db comes back NULL, and @table holds info as to the problem (either the table does not exist, or it is empty).
    BEGIN
        SET @tableHtml = @table;
        RETURN;
    END;
    
    --We have a good table. Use information_schema metadata for table to get column names.
    IF OBJECT_ID ('tempdb..##columnNames') IS not null DROP TABLE ##columnNames;
    CREATE table ##columnNames (column_name varchar(50), position int identity);
    
    SET @sql = 'USE ' + @db + '; INSERT into ##columnNames SELECT column_name from information_schema.columns where table_name = ''' + @table + ''' order by ordinal_position';
    EXEC master.sys.sp_executesql @sql;
    
    --use ##columnNames to create table ##columnPivot with the proper number of fields to hold data
    IF OBJECT_ID ('tempdb..##columnPivot') IS not null DROP TABLE ##columnPivot;
    CREATE table ##columnPivot (f1 varchar(200));
    
    DECLARE 
        @i int = 2,
        @fieldct int, 
        @column varchar(50), 
        @field varchar(200),
        @value varchar(100), 
        @html varchar(max) = '';
    
    SET @fieldct = (SELECT COUNT(*) from ##columnNames);
    WHILE @i <= @fieldct --loop through adding a field to ##columnPivot for each column. Max field len is 200.
    BEGIN
        SET @sql = 'ALTER table ##columnPivot ADD f' + cast (@i as varchar(2)) + ' varchar(200)';
        EXEC master.sys.sp_executesql @sql;
        SET @i = @i + 1;
    END
    --##columnPivot is constructed but empty. Columns are named f1, f2, f3, etc
    
    --construct dynamic SQL string that will be executed to populate ##columnPivot
    SET @sql = 'INSERT into ##columnPivot SELECT ';
    SET @i = 1;
    SET @fieldct = (SELECT count(*) from ##columnNames);
    
    WHILE @i <= @fieldct - 1
    BEGIN
        SET @column = (SELECT top 1 column_name from ##columnNames where position = cast (@i as varchar(2)));
        SET @field = 'CAST([' + @column + '] as varchar(200)),';
        SET @sql = @sql + @field;
        SET @i = @i + 1;
    END
    
    SET @column = (SELECT top 1 column_name from ##columnNames where position = @fieldct);
    SET @field = 'CAST([' + @column + '] as varchar(200)) FROM ' + @data_source;
    SET @sql = @sql + @field; --@sql now contains the SQL statement that will insert data from @data_source into ##columnPivot
    
    --execute @sql to insert into ##columnPivot the data from @data_source table
    EXEC master.sys.sp_executesql @sql;
    
    --format the output
    IF OBJECT_ID ('tempdb..#columns') IS not null DROP TABLE #columns;
    --use a copy of ##columnNames, because next steps delete from this table, and ##columnNames data is needed below. Does not need to be a global temp.
    SELECT *
    into #columns
    from ##columnNames
    order by position;
    
    SET @fieldct = (SELECT count(*) from #columns);
    SET @i = 1;
    
    --create the header row for the table containing column names from the @data_source
    WHILE @i <= @fieldct 
    BEGIN
        SET @field = (SELECT top 1 column_name from #columns order by position);
        SET @html = @html + '<td bgcolor="#dedede"><b>' + @field + '</b></td>';
        SET @i = @i + 1;
        DELETE from #columns where column_name = @field;
    END
    
    SET @html = '<tr>' + @html + '</tr>'; --now @html contains the header row of the output table
    
    
    --populate ##columnPivot by working through the data row by row. 
    ALTER table ##columnPivot add id_key int identity;
    
    DECLARE 
        @j int = 1, 
        @fieldcnt int, 
        @cell varchar(100), 
        @row varchar(500) = '';
    
    SET @i = 1;
    SET @fieldcnt = (SELECT count(*) from ##columnNames);
    SET @rcd_cnt = (SELECT count(*) from ##columnPivot);
    
    WHILE @i <= @rcd_cnt --this loop executes one time for each row of data
    BEGIN
        SET @j = 1;
        WHILE @j <= @fieldcnt --this loop executes one time for each column (cell) of data
        BEGIN
            SET @sql = 'SELECT @value = f' + cast (@j as varchar(2)) + ' from ##columnPivot where id_key = ' + cast (@i as varchar(2));
            EXEC master.sys.sp_executesql @sql, N'@value varchar(200) OUTPUT', @value OUTPUT;
            SET @cell = '<td>' + ISNULL (@value, '<br>') + '</td>'; --need to use <br> if the cell is empty
            SET @row = @row + @cell;
            SET @j = @j + 1;
        END
        SET @row = '<tr>' + @row + '</tr>';     
        SET @html = @html + @row;
        SET @row = '';
        DELETE from ##columnPivot where id_key = cast (@i as varchar(2));
        SET @i = @i + 1;
    END
    
    SET @tableHTML = '<table border="1" cellspacing="0" cellpadding="5">' + @html + '</table><br>'; 
    
    END
    

    Observe que estou invocando o procedimento "DataSourceCheck" para determinar se o parâmetro @data_source contém o nome de uma tabela válida. DataSourceCheck não precisa ser um procedimento separado - o SQL pode ser incluído diretamente no procedimento HtmlTable, mas eu o mantenho separado para modularidade e reutilização.

    Exemplo de uso do procedimento DataSourceCheck

    CREATE table ##foo (bar1 int, bar2 varchar(20), bar3 datetime)
    INSERT into ##foo values (1, 'Abcdef', getdate())
    INSERT into ##foo values (2, 'Ghijkl', '05/05/15')
    DECLARE @table varchar(200), @db varchar(50)
    EXEC dbo.DataSourceCheck
        '##foo', 
        @db output,
        @table output
    PRINT @db
    PRINT @Table
    

    Resultado

    tempdb
    ##foo
    

    Agora solte a tabela e veja o que acontece:

    DROP table ##foo
    
    DECLARE @table varchar(200), @db varchar(50)
    EXEC dbo.DataSourceCheck
        '##foo', 
        @db output,
        @table output
    PRINT @db
    PRINT @Table
    

    Resultado

    <br>Table ##foo does not exist or is improperly qualified.<br>
    

    Código para o procedimento DataSourceCheck

    /*
    Author: Leigh Haynes
    Date: February 2015
    Notes: Called by HtmlTable and CreateCsvFile to check validity of data source that is going to turn into an HTML table or a CSV file.
    */
    
    CREATE PROCEDURE [dbo].[DataSourceCheck] 
        @dataSource varchar (100) = NULL,
        @db varchar(50) = NULL output,
        @table varchar(100) = NULL output
    
    AS
    
    BEGIN
    
    DECLARE 
        @buffer varchar(100),
        @object varchar(100),
        @objectId bigint,
        @schema varchar(50),
        @rcd_cnt int,
        @tableHtml varchar(200),
        @sql nvarchar(1000)
    
    SET @buffer = @dataSource;
    
    --cannot accesss a local temp table. Return.
    IF SUBSTRING (@buffer, 1, 1) = '#' and SUBSTRING (@buffer, 2, 1) <> '#'
    BEGIN
        --use LEFT 25 to make sure the local temp table name isn't too long for the @table varchar(100) variable.
        SET @table = '<br>Table ' + LEFT (@dataSource, 25) + ' is a local temp table. Must use a global temp or permanent table.<br>';
        RETURN;
    END;
    
    --set up the object name in the right format so you can check the OBJECT_ID
    ELSE IF (SUBSTRING (@buffer, 1, 2) = '##')
    BEGIN
        SET @db = 'tempdb';
        SET @table = @dataSource;
        SET @object = @db + '..' + @table; --need to include tempdb so OBJECT_ID finds the temp table
    END;
    ELSE
    BEGIN
        --deal with schema
        SET @db = SUBSTRING (@buffer, 1, charindex ('.', @buffer) - 1);
        SET @buffer = replace (@buffer, @db + '.', '');
        IF SUBSTRING (@buffer, 1, 1) = '.' 
        BEGIN
            SET @schema = '..';
            SET @buffer = replace (@buffer, '.', '');
        END
        ELSE 
        BEGIN
            SET @schema = SUBSTRING (@buffer, 1, charindex ('.', (@buffer)) - 1);
            SET @buffer = replace (@buffer, @schema + '.', '');
        END
        SET @table = @buffer;
        SET @object = @dataSource;
    END;
    
    --does our data source exist? Check the object_id. If object does not exist, return.
    SET @objectId = OBJECT_ID (@object, 'U');
    IF @objectId is NULL 
    BEGIN
        SET @db = NULL;
        SET @table = '<br>Table ' + @dataSource + ' does not exist or is improperly qualified.<br>';
        RETURN;
    END;
    
    --we have a valid data source. Check that it has rows and notify if empty.
    SET @sql = 'SELECT @rcd_cnt = count(*) from ' + @dataSource;
    EXEC master.sys.sp_executesql @sql, N'@rcd_cnt int OUTPUT', @rcd_cnt OUTPUT; 
    IF @rcd_cnt = 0 
    BEGIN
        SET @db = NULL;
        SET @table = '<br>Table ' + @dataSource + ' is empty.<br>';
        RETURN;
    END;
    
    END
    

    Eu também tenho uma versão do HtmlTable que cria um arquivo CSV de uma tabela (em vez de uma tabela HTML).

    • 3

relate perguntas

  • SQL Server - Como as páginas de dados são armazenadas ao usar um índice clusterizado

  • Preciso de índices separados para cada tipo de consulta ou um índice de várias colunas funcionará?

  • Quando devo usar uma restrição exclusiva em vez de um índice exclusivo?

  • Quais são as principais causas de deadlocks e podem ser evitadas?

  • Como determinar se um Índice é necessário ou necessário

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve