プロシージャとトリガーの使い方-データベース管理

このQ&Aのポイント
  • データベースのテーブルAのaカラムが更新された場合、テーブルBの複数の列のbカラムをFalseからTrueに変更するトリガーとプロシージャの作成方法について教えてください。
  • プロシージャの作成方法は、FUNCTIONキーワードを使用してUPDATE文を実行し、複数の列を指定します。
  • トリガーの作成方法は、CREATE TRIGGER文を使用し、テーブルAのaカラムが更新された場合に実行されるプロシージャを指定します。
回答を見る
  • ベストアンサー

プロシージャとトリガー

Aというテーブルのaカラムが更新されれば、Bテーブルの列の中でAテーブルの列id含む列(複数)のbカラムをFalseからTrueに変更されるような、トリガー と プロシージャを作りたいのです。 考えていたのは、プロシージャは、 CREATE FUNCTION update_edit_b() RETURNS OPAQUE AS ' BEGIN (複数列指定?) NEW.b := 't'; RETURN NEW; END; ' LANGUAGE 'plpgsql'; プロシージャで、Bテーブルの複数列を指定するにはどうしたら良いでしょうか? トリガーは CREATE TRIGGER trgger_a AFTER UPDATE OF a ON Table_a FOR EACH STATEMENT EXECUTE PROCEDURE update_edit_b ; こんな感じでしょうか?

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

  • ベストアンサー
  • gacky-79
  • ベストアンサー率100% (14/14)
回答No.1

・NEW の値を使う場合には、FOR EACH ROW トリガを使う必要がある。 ・テーブルAに仕掛けたトリガの NEW は、テーブルAの行を表している。 といったあたりがポイントと思われます。 ↓こんな感じでどうでしょうか? CREATE FUNCTION update_edit_b() RETURNS TRIGGER AS $$ -- (OPAQUE はかなり古い書き方?) BEGIN UPDATE Table_b SET Column_b = true WHERE Table_b.A_id = NEW.id AND NOT Column_b; -- (複数回更新する際に、無駄なUPDATEを避ける) RETURN NEW; END; $$ LANGUAGE plpgsql; CREATE TRIGGER trgger_a AFTER -- (BEFOREのほうが若干効率が良いので、置き換えも検討すべし) UPDATE OF a ON Table_a FOR EACH ROW -- (STATEMENTではなくROWを指定) EXECUTE PROCEDURE update_edit_b;

参考URL:
http://www.postgresql.jp/document/current/html/sql-createtrigger.html
Beguate
質問者

お礼

ありがとうございます。大変参考になりました。 複数行はやめて1行としましたので、プロシージャは、こうしました。 CREATE FUNCTION update_edit() RETURNS OPAQUE AS ' BEGIN UPDATE Table_a SET a = true WHERE Teble_a.b_id= Table_b.id; RETURN NEW; END; ' LANGUAGE 'plpgsql'; トリガーについては、使っているPostgresQL のバージョン(8.4.9)ではカラムの変更は サポートされず、バージョン9からなそうで、とりあえず、バージョンアップしてみます。

関連するQ&A

  • Oracleのプロシージャについて

    Oracleのプロシージャについて教えてください。 現在、Aテーブル(カラム1、カラム2、カラム3、カラム4):件数40万件     Bテーブル(カラムA、カラムB、カラムC):件数50件 と言うテーブルがあります。 この中でデータ置換を行う必要があり、 Aテーブルのカラム2とBテーブルのカラムBが一致したらAテーブルの カラム3にBテーブルのカラムCで更新するプロシージャを作成しています。 通常のUpdate文で3000件単位でCommitを切るようにしていますが時間がかかります。 皆さんはこういう場合どういう手法でやられていますか? ご教授ください。 ちなみに、 サーバOS:Windows2008SERVER クライアントOS:Windows7 Oracle11 です。

  • トリガからプロシージャのコールについて

    データベースはOracle10gです。 あるテーブルAにレコードが登録されたタイミングで、 別のテーブルBにレコードを登録するトリガを作成しようとしています。 トリガ内に全ての処理を記述するとかなりの行数になりそうなので、 登録のプロシージャを作成し、トリガからコールしようと考えています。 Aに登録されたレコードのカラムの一部を、Bに登録するレコードでも使用したいのですが、 プロシージャに引数として渡す際、 使用したいカラムを一つずつ指定しなければならないのでしょうか? (使用したいカラムは10ほどあります。) トリガに 「REFERENCING NEW ROW R1」と記述して、 このR1を渡すことはできないのでしょうか?

  • トリガーの起動条件で悩んでいます。

    超初心者です。 うまく説明できないかも知れませんが助けて下さい。 うまく動作しない処理は、 [A_TBL]が更新時に履歴あり・なしにそれぞれトリガーを用意しているのですが、 履歴なしの場合は[A_TBL]がUPDATEされるだけなので、 『[A_TBL]がUPDATEされたタイミングで[B_TBL]もUPDATEする』 という起動条件にしています。 履歴ありの場合は[A_TBL]のデータをUPDATEで無効化(FLGを立てます)し、 その後、更新データをINSERTで登録しようと思っています。 そのためトリガーの起動条件を、 『[A_TBL]がINSERTされたタイミングで[B_TBL]のデータをUPDATEする』 としていますが、 [A_TBL]に新規登録時のトリガーの起動条件が、 『[A_TBL]にINSERTされたタイミングで[B_TBL]にもINSERTする』 としているので、 [A_TBL]にINSERTされると両方のトリガーが起動してしまい、 怒られました。 自分の作ったトリガーを書いておくので どのようにしたらよいのか教えていただけませんでしょうか? トリガーの書き方におかしな点があったらご指摘もお願い致します。 よろしくお願いしますm(_ _)m 新規登録のトリガー CREATE OR REPLACE TRIGGER INS_01 AFTER INSERT ON A_TBL FOR EACH ROW BEGIN INSERT INTO B_TBL( ID, 姓, 名, 住所, 本籍, 電話番号, 郵便番号 )VALUES( :NEW.ID, :NEW.姓, :NEW.名, :NEW.住所, :NEW.本籍, :NEW.電話番号, :NEW.郵便番号 ); END; / 更新のトリガー CREATE OR REPLACE TRIGGER UP_01 AFTER INSERT ON A_TBL FOR EACH ROW BEGIN UPDATE B_TBL SET 姓 = :NEW.姓, 名 = :NEW.名, 住所 = :NEW.住所, 本籍 = :NEW.本籍, 電話番号 = :NEW.電話番号, 郵便番号 = :NEW.郵便番号 WHERE ID = :NEW.ID ; END; /

  • Oracleデータベーストリガーのインポート

    Oracle8.1.7にて、あるAユーザーの所有物を全てExportし、その後、Bユーザーの所有物としてImportしようとすると、データベーストリガーのImport時にエラーが発生します。その他テーブルのImportは全て、成功しています。 (FROMUSER=A TOUSER=Bとしてimpしています。) そこで、LOGを見てみると、データベーストリガーのCreate時にトリガー自体はBユーザーの所有物としてImportしようとしているが、そのトリガー作成SQL文内のテーブル参照部分がAの所有物として指定されている為、エラーが発生しているという事がわかりました。 create trigger B.trigger_name ~ on A.table_name となっていました。 これは、impの仕様?バグ?なのでしょうか?それとも、なにか他にImport時に指定するオプションがあるのでしょうか? 回避方法等ご存知でしたら教えてください。 あと、このCreate Trigger文をSQL PLUSに手動で貼りつけて実行させようとしたら、何の反応もありませんでした。 まるで、このコマンドを認識していないという感じでした。SQL PLUSではCreate Trigger文は処理されないのでしょうか?因みにSQL Worksheetにて実行は出来ました。 こちらもご存知の方お願いします。

  • ストアドプロシージャでトランザクション処理をするにはどうすれば良いので

    ストアドプロシージャでトランザクション処理をするにはどうすれば良いのでしょうか? 複数のテーブルの行をストアドプロシージャで一括削除したいのですが、 エラーが発生した場合は、ロールバックしたいと思っています。 たとえば、 create table A (id INT, name VARCHAR(32)); // idと名前を持つテーブルA create table B (id INT, address TINYTEXT); // idと住所を持つテーブルB の二つのテーブル(idで紐付け)で、 Aの行が削除されたらBの行を削除するが、Bの削除でエラーが出た場合はAの削除をロールバックする。 という処理を行いたいのです。(ロールバックが可能であれば、ストアドプロシージャでなくても構いません。) どのように書けば良いのでしょうか? よろしくお願いします。

    • ベストアンサー
    • MySQL
  • トリガーのエラー

    ORA-04098: トリガー'sss.ssss'が無効で妥当性再チェックに失敗しました。というようなエラーが出ます。 トリガー自体は下のような単純なものです。 このエラーは単純にトリガーの文法などのエラーでしょうか?それとも、ORACLE環境など他の原因なんでしょうか? よろしくお願いします。 ------------------------------------- CREATE or replace Trigger XInsert AFTER INSERT ON sTable FOR EACH ROW BEGIN INSERT INTO xxxxxx (s,a,b,c,d) values(seq_a.NEXTVAL ,:new.a ,:new.b ,:new.c ,:new.d ); END;

  • OracleのTrigger(トリガー)について

    いつもご親切にありがとうございます。 Oracleのトリガーについて教えてください。 テーブルA ----------------- 日付 date型 品名 char(15) 営業所 cahr(5) フラグ char(1) データをINSERTする際に、下記のように変更したいです。 (1)日付が2月且つ、営業所が00001の場合は99999に変更、 (2)日付が2月且つ、品名の後ろ5桁が00001の場合後ろ5桁だけを99999に変更 下記のようにトリガーを作成しているんですけど、 (2)をどのように入れたらよいでしょうか? CREATE OR REPLACE TRIGGER TRG_テーブルA BEFORE INSERT ON テーブルA REFERENCING OLD AS OLD NEW AS NEW FOR EACH ROW BEGIN IF ( to_char(:NEW.日付,'YYYYMM') = '201502' ) AND ( :NEW.営業所 = '00001' ) THEN :NEW.営業所 := '99999'; END IF; END; / よろしくお願いします。

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

    Access2003とSQL Server2005Expressです。 初歩的な質問で恐縮です。 以下のストアドプロシージャのデータ取得先を、テーブルではなく 別のストアドプロシージャにしたいのですが、 その方法がわかりません。 CREATE PROCEDURE テスト AS SELECT コード, 社名, 住所, 電話 FROM 名簿     ↑     これをテーブルではなく、別のストアドプロシージャを     指定したのですが・・・。     ここをストアドプロシージャ名にするとエラーになります。     どうすればよろしいでしょうか?

  • Oracleのトリガーについて

    Oracleのトリガーについて質問です。 旧システムから新システムへデータ移行を行おうとしているのですが、 新システムではNEWテーブル(仮名)が新規で追加されています。 データ移行の方法として、旧システムのダンプファイルをエクスポートし、 新ステムにユーザを再作成後インポートしました。 その後、あらかじめ新システムでNEWテーブルのみテーブル指定のエク スポートを行っていたダンプファイルより、追加でインポートを行いました。 これでデータ移行完了と思っていたのですが、NEWテーブルのデータはトリガー により生成されるらしいのですが、どのタイミングで生成されるのでしょうか? データ移行完了時はデータ0件です。 NEWテーブルをインポートする順番が逆なのでしょうか? それともインポートではトリガーは起動しないのでしょうか? または、トリガーの仕組みが消えている(?)のでしょうか? (納入先に行かないと確認できない状態なので実際のデータベースが確認できません…) Oracleはあまり詳しくないため、わかりづらい質問かもしれませんが よろしくおねがいします。 【環境】 Oracle11g R2 Windows2008Server

  • ストアドプロシージャの作成

    MySQLでストアドプロシージャを作成しようと試みているのですが、 分からない事があります。 引数に、テーブルのカラムを指定したいんです。 具体的には、 func(column1, 100) などとして、 select * from table where finc func(column1, 100) > 1000 tableのcolumn1には数字が入っていて、引数の100と計算をして、 1000より大きい結果を返す・・・ みたいな感じです。

    • ベストアンサー
    • MySQL