このケースは、まさにループが適している (そして設計されている) ものです。
データベースの範囲外のことを行うため、それらにループを使用することは完全に正当です。
データベースは、データを保存し、これらのデータに対してクエリを実行して、最も便利な方法でデータを返すように設計されています。
リレーショナル データベースは、行セットの形式でデータを返すことができます。
カーソル (およびそれらを使用するループ) は、安定した行セットを維持するように設計されているため、各行でいくつかの処理を実行できます。
ここでいう「モノ」とは、純粋なデータベースのトリックではなく、外の世界に影響を与える実際のモノ、つまりデータベースが設計されているもの、たとえば Web ページにテーブルを表示する、財務レポートを生成する、電子メールを送信するなどのことを意味します。
純粋なデータベース タスク (ある行セットを別の行セットに変換するなど) にカーソルを使用するのは良くありませんが、あなたが説明したような目的でカーソルを使用するのはまったく問題ありません。
セット ベースのメソッドは、単一のトランザクション内で機能するように設計されています。
set-base クエリが何らかの理由で失敗した場合、データベースは以前の状態に戻りますが、送信された電子メールを「ロールバック」することはできません。エラーが発生した場合、メッセージを追跡できなくなります。