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

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

新規登録して質問してみよう
ただいま回答率
85.48%
SQL Server

SQL Serverはマイクロソフトのリレーショナルデータベース管理システムです。データマイニングや多次元解析など、ビジネスインテリジェンスのための機能が備わっています。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Q&A

解決済

3回答

2542閲覧

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

AGadget

総合スコア60

SQL Server

SQL Serverはマイクロソフトのリレーショナルデータベース管理システムです。データマイニングや多次元解析など、ビジネスインテリジェンスのための機能が備わっています。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

0グッド

0クリップ

投稿2019/05/04 23:06

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

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

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

自己解決

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

まず、.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 12:06

編集2019/05/11 12:15
AGadget

総合スコア60

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sazi

2019/05/11 12:49 編集

>「SQLに限らず、全てのプログラミングは1行ずつ(1処理ずつ)処理していくのが『プログラミングの王道』である」として「SQLにおいては『実行速度や開発速度に影響が出ない範疇では』極力、カーソル・フェッチを用いてデータを1行ずつ処理するべき」 集合を扱うSQLという言語特性を無視してる感じがします。 まあ、1行ごとにして処理を考える方が楽ですからね。 そういう場合のテーブル設計は往々にして正規化されていなかったりします。 複雑さや制限がある場合にフェッチループを考えるのですけど、一時テーブルを使用すると殆どフェッチループは必要ありません。
guest

0

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

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

投稿2019/05/05 02:09

編集2019/05/10 01:05
sazi

総合スコア25184

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

AGadget

2019/05/05 16:52

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

0

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

投稿2019/05/05 01:41

Orlofsky

総合スコア16415

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

AGadget

2019/05/05 05:33

回答ありがとうございます! そうですね。 履歴テーブルを使えると良いのですが、現状はテーブルA・テーブルBしか使えませんので……。 他に方法がありましたら、ご回答のほど、よろしくお願いします。
Orlofsky

2019/05/05 05:46

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

2019/05/05 16:48

ご返信ありがとうございます! 履歴テーブルの件ですが、駄目元で交渉してみようと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問