質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.04%

UPDATEと同時、あるいは後からログ出力する方法

解決済

回答 3

投稿

  • 評価
  • クリップ 0
  • VIEW 1,683

score 56

SQL Serverにて、UPDATEと同時、あるいはUPDATE後にログファイル(?)を出力する方法を探しています。
それも以下に挙げる制限を課した状態で、です。
個人的には不可能ではないかと思うのですが――可能・不可能含めて、ご回答のほど、よろしくお願い申し上げます。

前提として――全く同じ内容であるテーブルA・テーブルBがあります。
初めに、テーブルAに対してINSERTするなり、UPDATEするなりして内容を少し弄ります。
次に、テーブルAの内容をそのままテーブルBに上書きする形でUPDATEします。

これでテーブルAとテーブルBの内容は全く同じになる訳ですが、このときテーブルAとテーブルBを比較して差異のあったレコードを抽出して、.csvファイルに出力します。
ただし、以下の制限を課します。

1) csvファイルに出力するのはUPDATEと同時か、UPDATE後で無ければなりません。

2) テーブルA・テーブルB以外のテーブル・ファイル等は一切使用不可です。差異のあるレコードを抽出して、別テーブル等に保存しておき、テーブルA・テーブルBのUPDATE後にファイル出力に利用するといったことはできません。

3) 使用できる機能(?)はT-SQL・Sqlcmdユーティリティ・bcpユーティリティ・コマンドプロンプト(.batファイル)・Visual Basicの5つだけです。オンライン上の機能を利用したり、PowerShellなどの上記以外の機能(言語?)は利用できません。

この3つの制限さえ無ければ簡単にできる処理だとは思うのですが、この制限を課した状態で、この処理は実行できるものなのでしょうか。

長くなりましたが、ご回答のほど、よろしくお願い申し上げます。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

0

履歴テーブルを用意して、トリガーで ログ情報を書き込む。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/05/05 14:33

    回答ありがとうございます!

    そうですね。
    履歴テーブルを使えると良いのですが、現状はテーブルA・テーブルBしか使えませんので……。

    他に方法がありましたら、ご回答のほど、よろしくお願いします。

    キャンセル

  • 2019/05/05 14:46

    ログをテキストファイルに出力する事も考えられますが、ROLLBACKして再実行するとログがダブって出力されます。
    更新履歴をテーブルに記録することはよくあるやり方です。履歴テーブルを作らせてもらえるように上長と交渉されては?

    キャンセル

  • 2019/05/06 01:48

    ご返信ありがとうございます!

    履歴テーブルの件ですが、駄目元で交渉してみようと思います。

    キャンセル

0

トランザクション制御を行えば可能だと思います。
SQL Server の明示的なトランザクション制御方法

一時テーブルを使用しても可能でしょう
【SQL SERVER】 一時テーブル。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/05/06 01:52

    ご回答ありがとうございます!

    まだ具体的な手法が思いつかないのですが、ひとまずトランザクションを利用して何とかできないか試してみようと思います。

    キャンセル

check解決した方法

-1

上長に解決方法を聞いてきましたので記載致します。
厳密には上長の考えを、私なりの方法で実現させたものになります。

まず、.batファイルを用意し、Sqlcmdユーティリティからストアドプロシージャを呼び出します。
このときSqlcmdユーティリティには-sオプション・-oオプションを設定して、実行したストアドプロシージャの抽出結果を.csvファイルに出力させるよう設定します。

ストアドプロシージャは以下の流れで処理します。
1) カーソルで不整合のあったレコードを1行ずつ抽出。
2) 抽出したレコードの主キーを変数に代入。
3) UPDATE文のWHERE句に変数の値を指定してUPDATE。
4) 変数の値をユーザー定義テーブル型変数にINSERT。
5) 1)~4)をフェッチで繰り返して全てのレコードを処理。
6) ユーザー定義テーブル型変数をSELECT文で出力。ここで出力したことでSqlcmdユーティリティが出力結果を.csvファイルに出力してくれる。
7) ストアドプロシージャ終了。それに伴い.batファイルも終了。

この方法を採ることで3つの制限を全て回避して処理を実現させることができました。
以上です。

//余談
ところで、この処理ですが個人的には、かなり無駄というか非効率だと感じています。
カーソルといい、ユーザー定義テーブル型変数といい「わざわざ、そんなことをしなくても……」というのが本音です。

ただ、上長としては――まず、大前提として「SQLに限らず、全てのプログラミングは1行ずつ(1処理ずつ)処理していくのが『プログラミングの王道』である」として「SQLにおいては『実行速度や開発速度に影響が出ない範疇では』極力、カーソル・フェッチを用いてデータを1行ずつ処理するべき」とのことでした。

仰っていることは分からなくはないのですが、データをまとめて処理できるのがSQLの良いところなので(クエリを書いたりするのも楽ですし)、それは、うーん、どうなのかなぁ、というところです。

上長に遠く及ばぬ未熟者ゆえ納得し難いお考えでした。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/05/11 21:45 編集

    >「SQLに限らず、全てのプログラミングは1行ずつ(1処理ずつ)処理していくのが『プログラミングの王道』である」として「SQLにおいては『実行速度や開発速度に影響が出ない範疇では』極力、カーソル・フェッチを用いてデータを1行ずつ処理するべき」

    集合を扱うSQLという言語特性を無視してる感じがします。
    まあ、1行ごとにして処理を考える方が楽ですからね。
    そういう場合のテーブル設計は往々にして正規化されていなかったりします。
    複雑さや制限がある場合にフェッチループを考えるのですけど、一時テーブルを使用すると殆どフェッチループは必要ありません。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.04%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る