• ベストアンサー

ストアド、トリガーの同時呼出

SQL Server 2008 です。 在庫管理DBを作ろうとしています。 複数のクライアントから一つのレコードに更新が発生した場合を考えています。 複数のクライアントから同一のストアド(在庫引落)を読んだ場合 呼ばれたストアドは同時に複数走るのでしょうか、一つずつ走るのでしょうか? こんな時(在庫引落)はストアドにパラメータを渡すよりも、一時テーブルに 書き込んで、トリガーで更新(引落)ってな事をした方がいいのでしょうか? その場合トリガーも同時に走るのでしょうか?一つづつでしょうか? 複数のクライアントから更新がかかり、直接レコードを更新出来ないような 場合はSQLではどう処理するのがメジャーなんでしょうか? オフコンでは仮想記憶って云うのがあって、そこに書き込むとバックグランドで ウェイティングしていたプログラムが一件ずつ読み込んで更新する仕組みでした。 更新が終わると、また読込みでウェイティングする仕組みです。 複数の端末から一つの仮想記憶に書きこみ、読込みはシーケンシャルで一件ずつですので、 在庫がマイナスになることは合っても、整合性が取れなくなることはありませんでした。 こんな仕組みでSQLに移行したいと考えています。

質問者が選んだベストアンサー

  • ベストアンサー
  • jamshid6
  • ベストアンサー率88% (591/669)
回答No.3

原則論から言えば「トリガは使わなくて済むならばできるだけ使わないようにする」が正しいです。 ただし、私はトリガーでやっていいケースはあると考えています。 ・その2つのテーブルの間に極めて密な関係がある(例外なく反映させる) ・1つのテーブル以外はアプリケーションサイドで通常更新対象と認識されていない ・複数のルートでテーブル更新が掛けられる可能性がある ・ユーザがトリガーを無効にできる権限を持っていない 具体的には数十万件の取引データからリアルタイムの累積残高を取得・表示させるための残高テーブルの更新にトリガを使用したことがあります。 今回のケースはストアドでもトリガでやってもいいケースだと思いますが、以下の点は留意してください ・SQL Serverには行トリガがないので、複数更新が掛けられたときの処理を組み込む  (複数行更新は不可とするか、全部が在庫条件を満たしたときだけOKとする) ・在庫がマイナスになる場合はトリガ内でRAISERRORを発行する ・呼び出し元(ストアドでもアプリでも)はエラートラップが必須

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (2)

  • jamshid6
  • ベストアンサー率88% (591/669)
回答No.2

>複数のクライアントから同一のストアド(在庫引落)を読んだ場合 >呼ばれたストアドは同時に複数走るのでしょうか、一つずつ走るのでしょうか? ストアドプロシージャは同時に走りますが、処理の中で同じレコードに対する排他ロックを取得できなかった方は待つことになります。だから通常はレコードをロックする時間が極力短くなるようにコーディングします。 #1さんの書かれた通り、質問者さんの懸念されている内容はDBMSの本質の問題(それが起きたらDBMSじゃないでしょうというような)な気がします。

SEsyo
質問者

補足

排他ロックがかかるのは解っていたのに、疑問点とやりたい事が ごちゃ混ぜになった質問をしてしまいました。 そこで再度質問ですが、 出庫データが累積テーブルに書き込まれたらトリガーで在庫から 引き落とす仕組み(insertの数量を引落、deleteの数量を戻し)を 作ろうと考えたのですが、これは普通のやり方でしょうか? それともストアドへキーと数量を渡し在庫の更新が完了後 累積テーブルに書き込む方がいいのでしょうか? 複数の端末から同時に同じ物を出庫されると入力画面のチェック時 は在庫不足にならなくても、更新時にマイナスになることは想定しています。 これもトリガーで在庫が更新された時に確認しマイナスの場合は 何らかのアラームになるような事を考えています。 これまでトリガーは履歴の採取にしか使っていなかったのですが、 トリガーをこんな風に利用してもいいのでしょうか? (トリガーはこんな風に利用するものなのでしょうか?)

全文を見る
すると、全ての回答が全文表示されます。
回答No.1

何のために、DBMSを使っているのですか? DBMSを使う理由の一つが、排他制御で同時更新を抑止したり、トランザクションといった単位で複数の表、複数の行の更新を有効にしたり無効にしてデータの整合性が保証されることですよね?

SEsyo
質問者

お礼

>何のために、DBMSを使っているのですか? 駆け出しの性で使う理由を考えて使っているわけではありません。 PCの素人がエクセルを使う様な感じです・・・ 再度自分の文章を読み直してみて、やりたい事と質問も合いません。 ご指摘通り通り大きな考え違いをしていたようです。 ありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • ストアドを使う場合

    お世話になります。 ストアドをどういったときに使用したらいいか分かりません。 ストアドを使うとネットワークの負荷を軽減できるというのは 分かるのですが、単純に1テーブルを参照する場合は ストアドでなくてもそれほど変わらない? 複数にリンクがある場合に使用するべきなのですか? それともトータル値を取得したり計算を行わせたりする場合 に使用するべきなのでしょうか? 例えばVBにADOなどで直接SQL文を書くのと ストアドを呼ぶのでは 何を基準に直接SQLをよんでいいのか、ストアドを呼んだ方がいいのか 基準となる考え方がわかりません。 質問文が分かりずらかったらすみません。 お分かりになる方ご回答お願いします。

  • ストアドプロシージャ呼び出しのSQL文について

    こんにちは! 現在、EJBからDBサーバー内のストアドプロシージャを呼び出して 実行させたいのですが、「Connection」の「prepareCall」を 使用する場合にその引数のSQLをどうやって書けばいいのか わからないで困っています。 一応、登録・更新のSQLなので、データを含んだ形になるのですが、 どなたかご存知の方いらっしゃいましたらご指導ください。 よろしくお願いします。

    • ベストアンサー
    • Java
  • PL/SQLトリガー機能

    PL/SQLでトリガーを使って下記処理をしたいのですが教えてください。 処理内容 a在庫数テーブルの在庫数がUPDATE(After UPDATE)するたびに b在庫数テーブルにa在庫数の店CD(KEY1)と商品CD(KEY2)と取引日と当日売上日と在庫数を追加(INSERT) この時、 b在庫数テーブルのkey店CD(KEY1)と商品CD(KEY2)と取引日(KEY3)が同じ場合、在庫数のみを更新(UPDATE)する。 上記の事柄のトリガー機能・処理分を教えてください。 よろしくお願いします。

  • ストアドのフィールド指定方法

    MS SQL Server7.0のストアドプロシージャについての質問です。 複数のフィールドを持つテーブルの、各フィールドに入ってる値を順番に調べる方法について教えて下さい。 具体的には、フィールドは"月日_01"から"月日_31"まであり、各フィールドには"1"か"0"のどちらかの値を持ってます。この31個のフィールド値を調べて、"1"と"0"の各合計値を求めたいです。 ADOのレコードセットなら、Fields でフィールドのインデックス値を指定出来ますので簡単にループ処理できますが、ストアドの場合インデックスによるフィールド指定がうまく出来ません。 現在はIF文で各フィールドを一つづつ判定してる状態です。もっとスムーズに行う方法がありましたらご教授下さい!どうぞ宜しくお願いします。

  • SQLServerの同時接続

    質問させていただきます。 SQLSerever2000でSELECTの結果を返すだけのストアドプロシージャがあるのですが、複数のユーザーが同時に実行すると、単独で実行した場合に比べて処理速度が低下するという現象が起こっています。 このSELECT(のみ)同士で処理が遅くなることについて原因がわからずに困っています。 今わかっていることは (1)SQL文が非常に複雑(サブクエリの結合も多い)で対象データの件数も多い。 (2)実行時はUPDATEなどの更新処理は一切入っていない(トランザクションも張っていない)。 (3)SELECT時にWITH(NOLOCK)を使用しても結果は変わらない。 (4)分離レベルをUNCOMMITEDにしてみたが結果は変わらない。 (5)プロファイラ上で実行時デッドロックが発生していないことは確認済み (6)ほぼ同時に実行するとやたら遅く、少しタイミングをずらして実行すると、あまり影響し合わない。 (7)処理速度の遅延は同時実行ユーザーのお互いについて発生する(※片方だけが待つわけではなく、ほぼ同時に開始した処理は単独の場合と比べて長い時間をかけて同時に終了する) 以上の事から、ストアドプロシージャの実行処理そのものは並列処理となっているが、SELECT内でのサブクエリ単位の情報取得→結果を返す・・・の処理まわりは並列実行できず、サブクエリごとにお互いを邪魔しあうような状態が発生しているように見えます。 このような想定はそもそも見当違いなのでしょうか? 実際にSELECTのみのSQL同士を複数ユーザーで実行するだけでお互いの処理に影響しあうようなことはあるのでしょうか? また、SELECT時の『共有ロック』について複数ユーザーの同時実行には何の影響もない(更新ロックではないので、ロックの取得は可能)の認識ですが、認識誤りはないでしょうか? DBにはあまり詳しくないのでおかしな事を質問しているかもしれませんが、宜しくお願いいたします。

  • 登録する方法

    SQL server 2000で接続セッションのIPアドレスをトリガーでテーブル登録する方法を教えてください。あるテーブルの「更新IPアドレス」という文字列項目に、そのレコードが固定編集された時にクライアント端末のIPアドレスをトリガーで、登録したいのですが、方法を教えてください

  • Accessプロジェクト ストアドプロシージャでのデータ更新

    AccessのMDBをADPへ作り変えています。 MDBの更新クエリーの場合、「レコードの更新」欄に更新したい値を記述します。たとえば、ユーザー定義関数を使っている場合は、ユーザー関数名([○○○]) ・・・。 これと同じことを、ADPのストアドプロシージャで行う場合はどのようにすればよいのでしょうか? スツアドプロシージャは「デザイナを使用してストアドプロシージャを作成する」を使って作成しています。ここで、「新しい値」欄に ユーザー関数名(○○○) と記述すると、 ”ADOエラー:"ユーザー関数名"は関数名として認識されません” となります。 初めてADPを使用するのでよくわかりません。 以上、よろしくお願いします。

  • ストアド。存在チェックをしてから登録したい。

    SQLServer2005環境です。 同じ構造のテーブルA、Bがあり、AのデータをBにコピーしたいと思っています。 Aのデータは最新のデータ、Bの中にあるのは古いデータなので、もしキーが かぶるレコードがあれば、Updateをかけ、なければInsertをするような仕組みに したいと思っています。 更に可能であれば、Aに存在しないデータがBにあった場合は、Deleteしたいです。 一度BをDeleteしてInsertすれば話が早いのですが、そうもいかず、UpdateとInsertを 交え、小出しに更新するような形にしたいのです。 2008であれば、Merge文という便利なものがあるのですが、2005では上のような 動作をストアドで実現するのは難しいでしょうか。 サンプルコードですとか、解説しているサイトなどがありましたら、教えていただけますと 大変助かります。 宜しくお願いします。

  • 同一レコード更新時の排他制御

    Oracle9iです。 C/S開発で、VB.NETで画面を開発します。 DBの更新は、画面よりストアドプロシージャを使って行います。 複数ユーザが同一レコードを同時に参照し、同一レコードに対して更新された場合、参照時の更新日時と異なる場合はエラーとするよう設計されています。(つまり、後更新はエラー) この排他チェックロジックを画面側で実装しようとしておりますが、この排他チェックロジックを画面側で実装せずに、Oracleよりエラーレコードを受け取ることによる排他制御を行うことはできないでしょうか? ご教授のほどよろしくお願いいたします。 また、参考サイトあれば、その紹介だけでも助かります。

  • Oracleストアドプロシージャについて

    現在、夜間バッチで海外FTPサーバーからCSVファイルをDWHサーバーに格納後、 同DWHサーバー内のOracleテーブルにInsertするという処理の開発をしているのですが、 CSVの取得はDOSバッチとTeratermのマクロで取得しようと思っています。 しかし、CSVファイルのInsert処理はPL/SQLで開発を行おうと考えています。 それは、Insert後にそのテーブルと別サーバーのOracleテーブルを使用してデータの加工を行い、 その結果をDWHテーブルにロードしなければいけないからです。 ちなみに、今まではVBしか触ったことしかなくPL/SQLやバッチの作成はは初めてです。 そこで質問なのですが、PL/SQLで他のサーバーのテーブルとリレーションは出来るのでしょうか? (VBAでは1つのサーバーにしか同時接続できなかったため) またその場合のフローチャートのイメージが出来ないのですが、箇条書き程度で結構ですので教えていただけないでしょうか?(どこでストアドプロシージャに処理が移行するのかなど....) 長い文章でわかりにくいと思いますが、識者の方がいれば教えていただければ幸いです。