Sql server 为结果集中的每一行发送电子邮件

Sql server 为结果集中的每一行发送电子邮件,sql-server,sql-server-2005,tsql,Sql Server,Sql Server 2005,Tsql,我想使用sp_send_dbmail为结果集的每一行发送一封电子邮件 在不使用循环的情况下,实现这一点的合适方法是什么 编辑:我不是坚持循环在这里是不合适的,但是有一种基于集合的方法来做到这一点。我尝试过创建一个函数,但函数无法调用其中存储的进程。只有另一个func或扩展sp(我也不希望这样做)。这种情况正是循环的优点(也是设计的目的) 因为您所做的事情不属于数据库范围,所以对它们使用循环是完全合法的 数据库设计用于存储数据并对这些数据执行查询,这些数据以最方便的方式返回 关系数据库可以以行集的

我想使用sp_send_dbmail为结果集的每一行发送一封电子邮件

在不使用循环的情况下,实现这一点的合适方法是什么


编辑:我不是坚持循环在这里是不合适的,但是有一种基于集合的方法来做到这一点。我尝试过创建一个函数,但函数无法调用其中存储的进程。只有另一个func或扩展sp(我也不希望这样做)。

这种情况正是循环的优点(也是设计的目的)

因为您所做的事情不属于数据库范围,所以对它们使用循环是完全合法的

数据库设计用于存储数据并对这些数据执行查询,这些数据以最方便的方式返回

关系数据库可以以行集的形式返回数据

游标(以及使用它们的循环)被设计成保持一个稳定的行集,这样就可以完成每一行的某些事情

这里所说的“东西”,我指的不是纯粹的数据库技巧,而是影响外部世界的真实事物,即数据库设计的目的,无论是在网页上显示表格、生成财务报告还是发送电子邮件

对于纯数据库任务(比如将一个行集转换为另一个行集),使用游标是不好的,但是对于您描述的那样的任务,使用游标是非常好的

基于集合的方法设计为在单个事务中工作


如果您的set base查询由于某种原因将失败,您的数据库将恢复到was before中的状态,但您无法“回滚”已发送的电子邮件。如果出现错误,您将无法跟踪邮件。

这不是最佳做法,但如果您希望避免循环:

您可以创建一个“SendMails”表,在Insert上有一个触发器

从触发器内部调用sp_send_dbmail

然后你会:

Truncate Table SendMails

insert into SendMails (From, To, Subject,text) Select field1,field2,field3,field4 from MyTable

如果您需要每行发送电子邮件,则必须执行逐行操作。这不是一个标准的基于集合的动作

您可以在SQL中使用它,也可以在客户端语言中使用“for each”


我不会从触发器发送电子邮件顺便说一句:触发器执行时,您的事务处于打开状态

在SQL Server Reporting Services中设置数据驱动订阅:-D


对我来说,听起来像是SSRS要求——TSQL本身并不是为报告而设计的。

实现这一点的最佳方法是将电子邮件发送逻辑放在用户定义的函数中

然后,您只需从MyTable中调用SELECT MyEmailFunc(emailaddress)

它避免了循环,您甚至可以在update语句中使用它来显示电子邮件已发送。例如:


UDPATE MyTable SET SENT=MyEmailFunc(emailaddress),其中SENT=0

循环似乎非常适合这种情况。你能解释一下为什么要避免它们吗?循环对于这类事情来说是个坏主意。请参见下文,我不喜欢编写循环,更喜欢使用基于集合的方法。如果查询在这两者之间失败,该怎么办?您将丢失结果集,甚至不知道上次成功发送的电子邮件是什么。只能从函数中执行函数和扩展存储过程。只需使用UPDATE语句即可。函数应该有错误捕获代码并发送适当的结果。@克里斯:我的意思是如果你的
更新失败怎么办?例如,表被锁定,或者空间不足。@Quassnoi:update语句仅在能够获得锁的情况下执行函数;所以这不是问题。至于磁盘空间不足,没有什么可以工作,所以你有更大的问题。我知道,这是可以使用这种类型的事情循环,但不知道是否有其他方法。希望有人会觉得你的文章很有帮助:基于PSet的操作不适合这样做。我试着做你10年前在PostgreSQL中描述过的事情(打印餐厅账单),结果那是一场噩梦,因为我描述了很多原因。只需使用循环:)sql server中的新电子邮件实际上并不等待发送电子邮件。它被放置在一个队列中,并由一个单独的处理器处理。exeI仍然不会在触发器中执行此操作,也不会在触发器中循环