sp_send_dbmail是否与@query param同步

时间:2017-03-09 19:38:42

标签: sql-server

让我们假设我有一个表ExchangeSession,字段已处理。

我需要使用Processed = 0的所有ExchangeSession发送电子邮件,然后将这些会话更新为Processed = 1.像这样:

EXEC msdb.dbo.sp_send_dbmail
@profile_name = 'SomeProfile',
@recipients='SomeAddress',
@subject = 'SomeSubject',
@body = @bodyparam,
@body_format = 'TEXT',
@query = N'SET NOCOUNT ON; select * from ExchangeSession where Processed = 0',
@execute_query_database = @dbnameparam,
@attach_query_result_as_file = 1,
@query_attachment_filename = 'report.csv',
@query_result_header = 1,
@query_result_width = 32767,
@query_result_separator = @delimiterparam,
@exclude_query_output = 1,
@append_query_error = 0,
@query_no_truncate = 0,
@query_result_no_padding = 1;

update ExchangeSession
set
  Processed = 1
where
  Processed = 0

sp_send_dbmail会相对于批处理还是异步地同步执行我的查询?换句话说,是否有可能在电子邮件中我没有得到所有未经处理的会话?

2 个答案:

答案 0 :(得分:1)

答案是肯定的。查询参数执行是相对于批处理同步的。 做了以下测试:

insert dbo.[CallLog]([Name]) values ('BeforeMail')

set @queryparam = N'SET NOCOUNT ON;
insert dbo.[CallLog]([Name]) values (''Attachment'');
SELECT
    0 as [ID],
    ...'
...
EXEC msdb.dbo.sp_send_dbmail 
    ...   
    @query = @queryparam,
    ...

insert dbo.[CallLog]([Name]) values ('AfterMail')

瞧,CallLog中的结果:

LogID   Name
801 BeforeMail
802 Attachment
803 AfterMail

我还查看了 sysmail_allitems sysmail_mailattachments sysmail_allitems 中的 send_request_date 值与 sysmail_mailattachments 中的 last_mod_date 值完全相同。 sysmail_allitems sent_date 的值略有不同。

因此,sp_send_dbmail在批处理中同步执行查询,将结果保存到文件中,然后再发送电子邮件。

答案 1 :(得分:0)

我不是100%肯定,但我认为新条目可能会在发送电子邮件和更新记录之间潜入您的ExchangeSession表。我会这样做安全:

update ExchangeSession
    set Processed = 2   -- This procedure should be the only place that sets Processed to 2
    where Processed = 0

EXEC msdb.dbo.sp_send_dbmail
    ....
    @query = N'SET NOCOUNT ON; select * from ExchangeSession where Processed = 2',
    ....

update ExchangeSession
    set Processed = 1
    where Processed = 2