Oracleの変更表エラーを回避するトリガーの作成方法とは?

このQ&Aのポイント
  • Oracleの変更表エラーを回避するためには、複合トリガーを使用する必要があります。
  • 作成したトリガーは、挿入後に実行されます。
  • トリガーの中で新しい社員番号を生成し、それを社員テーブルに挿入するようになっています。
回答を見る
  • ベストアンサー

orace 変更表エラーを回避するトリガー

お世話になります。 今回、あるTBL1のフィールド:[氏名]を入力すると同テーブルのフィールド:[社員番号]が自動で セットされるようなトリガーを作成しようとおもっています。 しかし、変更表の更新には複合トリガーを使用しなければ出来ないというのはわかったのですが、 うまいことコンパイルできません。下記に前提条件と自分なりに作成したトリガーをを記載しますので どなたか助けてください。 <前提条件> ・セットされる社員番号はプライマリーキーとなっている。 ・更新される条件はTBL1のフィールド:[データ区分]が2or3のとき <作成したトリガー> CREATE OR REPLACE TRIGGER TRG_SET_AUTO_SHAIN_NO FOR INSERT ON CM_PORTAL_SHAIN COMPOUND TRIGGER REFERENCING OLD AS OLD NEW AS NEW WHEN (NEW.DATA_KBN in (2,3)) DECLARE GRP_CD VARCHAR2(3); SEQ_NO NUMBER(4); NEW_SET_NO VARCHAR2(7); AFTER STATEMENT IS BEGIN IF :NEW.DATA_KBN = 2 THEN select SQ.GROUP_CD,SQ.SEQUENCE_NO + 1 into GRP_CD,SEQ_NO from CM_HAKEN_GROUP_SEQUENCE_MT SQ where SQ.GROUP_CD = '999'; ELSE select SQ.GROUP_CD,SQ.SEQUENCE_NO + 1 into GRP_CD,SEQ_NO from CM_HAKEN_GROUP_SEQUENCE_MT SQ where SQ.GROUP_CD = '888'; END IF; NEW_SET_NO := substr(GRP_CD,LPAD(SEQ_NO,4,0)); INSERT INTO CM_PORTAL_SHAIN (SHAIN_NO,SHIMEI_LOCAL,DATA_KBN) VALUES (NEW_SET_CD,:NEW.SHIMEI_LOCAL,:NEW.DATA_KBN); AFTER EACH ROW IS BEGIN INSERT INTO CM_PORTAL_SHAIN (SHAIN_NO) VALUES (NEW_SET_NO) END; / ちなみにこれでコンパイルするとエラーが発生します・・・ どこがいけないのでしょうか?

  • Oracle
  • 回答数2
  • ありがとう数2

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

  • ベストアンサー
  • yamada_g
  • ベストアンサー率68% (258/374)
回答No.2

複合トリガーについては理解できていないのですが、質問の内容でも必要なのでしょうか。 >あるTBL1のフィールド:[氏名]を入力すると同テーブルのフィールド:[社員番号]が自動でセットされるようなトリガー だけなら、普通のトリガーでいいと思うのですが。 たとえば、 CREATE OR REPLACE TRIGGER TRG_SET_AUTO_SHAIN_NO BEFORE INSERT ON CM_PORTAL_SHAIN FOR EACH ROW WHEN (NEW.DATA_KBN in (2,3)) DECLARE GRP_CD VARCHAR2(3); SEQ_NO NUMBER(4); NEW_SET_NO VARCHAR2(7); BEGIN IF :NEW.DATA_KBN = 2 THEN GRP_CD := '999'; ELSE GRP_CD := '888'; END IF; --社員番号はグループごとに連番で振りたいということですよね? --質問文のコードでは連番取得後にテーブルの更新処理をしていないですが必要じゃないですか? --実際にはSEQUENCEを使った方がいいような気がします select SQ.GROUP_CD,SQ.SEQUENCE_NO + 1 into GRP_CD,SEQ_NO from CM_HAKEN_GROUP_SEQUENCE_MT SQ where SQ.GROUP_CD = GRP_CD for update; update CM_HAKEN_GROUP_SEQUENCE_MT set sequence_no = seq_no where GROUP_CD = GRP_CD; --SHAIN_NOに値を設定するだけで、トリガー内でINSERTやUPDATEを発行する必要はない --質問では、NEW_SET_NO := substr(GRP_CD,LPAD(SEQ_NO,4,0)); となっていましたが --本当は連結するのだろうと勝手に想像しました。 :new.SHAIN_NO := GRP_CD || LPAD(SEQ_NO,4,'0'); end; / こんな感じでも。

anman0201
質問者

お礼

ご回答ありがとうございます。 まさに言われてとおりです! というかソースをそのまま書いたらうまくいきました! シーケンスの更新部分も必要な箇所でしたので考慮頂き非常に助かりました。 こんなスマートな方法があったんですね。 大変勉強になりました。 本当にありがとうございます。

その他の回答 (1)

  • nora1962
  • ベストアンサー率60% (431/717)
回答No.1

今、検証する環境が手元にないのですが、 http://otndnld.oracle.co.jp/document/products/oracle11g/111/doc_dvd/appdev.111/E05670-03/triggers.htm#CIHIEFAE を見る限り ・複合トリガーにDECLARE宣言はない ・各トリガーのセクション(AFTER STATEMENT IS BEGIN で始まる)は「ND AFTER STATEMENT」で終わっている。 などが気になります。

anman0201
質問者

補足

ご回答ありがとうございます。 頂いたリンクから例文を参照しましたが、 FOR INSERTの部分で構文エラーが発生しているようです。 例文をそのまま実行してみてもFORの部分でエラーが発生します。 この部分はAFTER、BEFORE、INSTEAD OFを指定しなければいけないのでしょうか?

関連するQ&A

  • トリガーのエラー

    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;

  • マージレプリケーション ID値の返し方

    知識が浅く、自力で解決できないのでご協力お願い致します。 SQL Server2005を使用しています。 サーバーAとサーバーBで、マージレプリケーションで同期をとっているテーブルがあります。 Aの方のテーブルにストアドプロシージャを実行してINSERTし、そのID値(シーケンス番号)を直後にアウトプットとして取得したいのですが、どうも上手くクエリがうまく書けません。 例: AとBのあるテーブルには自動付番のシーケンス番号60までデータがあります。 AにINSERTして新規に追加されたデータのシーケンス番号は61となるので アウトプットとしてその61を返したいのですが、 マージの影響でコミット前のIDを返すのでしょうか、2など全く違った値が返ってきます。 実際にテーブルを確認すると、ちゃんとAもBもシーケンス番号61で新規追加されています。 現状のクエリではINSERT文のあとに 『SET @no_seq = @@IDENTITY』と記述していて、 マージレプリケーションを解除していれば@no_seqに正しいID値を返します。 他には ・@no_seq = SCOPE_IDENTITY ・@no_seq = IDENT_CURRENT('table_name') を試しましたが結果は同じでした。 クエリの書き方なのか、あるいは マージレプリケーションの設定にも詳しくないので なにか原因に心当たりがあれば教えて頂きたいです。 よろしくお願い致します。

  • OracleでINSERT文のループ

    INSERT文で何万件ものデータをテーブルに挿入したいのですが、 SUBSTRBまたはSUBSTR関数で何バイト分あるいは何文字分抽出して その部分の値をインクリメントさせる記述のしかたがわかりません。 INSERT INTO aaa (ID,YEAR,CLS,NO,THING,CD,LAND,USER,GROUP) VALUES ('30000003000','2000','2','85000','001','55555','10','test','1'); INSERT INTO aaa (ID,YEAR,CLS,NO,THING,CD,LAND,USER,GROUP) VALUES ('30000003001','2000','2','85001','001','55555','10','test','1'); INSERT INTO aaa (ID,YEAR,CLS,NO,THING,CD,LAND,USER,GROUP) VALUES ('30000003002','2000','2','85002','001','55555','10','test','1'); INSERT INTO aaa (ID,YEAR,CLS,NO,THING,CD,LAND,USER,GROUP) VALUES ('30000003003','2000','2','85003','001','55555','10','test','1'); ・ ・ ・ と、いう感じで、IDとNOのみ、値をインクリメントさせて大量のデータを 挿入したいのですが、SUBSTRB関数やループなどを使って効率的に行うやり方がわかりません。どなたか、ご教授ください。

  • Accessの不一致クエリで

    不一致クエリでテキスト型の2桁の数値05が5となってしまいます。 ExeStr = "INSERT INTO Master (製品CD, 製品名, F_No, LineCD, 発生元, " _ & "登録年月日, 更新年月日) SELECT " _ & "NEW.製品CD," _ & "NEW.製品名, " _ & F_No & ", " _ & "NEW.部門CD AS LineCD, '" _ & syoribi & "', " _ & "#" & myDate & "#, " _ & "#" & myDate & "# " _ & "FROM NEW LEFT JOIN OLD " & _ "ON (NEW.製品CD = OLD.製品CD) " & _ "WHERE OLD.製品CD Is Null;" cn.Execute ExeStr 元のNEWテーブルのF_Noは05となっています。 MasterテーブルのF_Noの結果が05としたいのですが、5ではいってしまいます。 どうしたら良いでしょうか。 ちなみにフィールドはテキスト型のフィールドサイズ2にしています。 テーブルのNEWとOLDの不一致でOLDに無いものをMasterに追加しております。

  • 外部ファイルを使用するシェルの作成について

    こんにちわ。プログラミングど素人のpcunixと申します。 これまで直接シェルの中身を編集していましたが、今後利用回数が増えたことから、編集していた箇所を外部ファイル(txtでもcsvでも何でも良い)へ書き込んでおき、その内容を取り込みたいと考えております。 「今まで使用していたシェル」 #!/bin/sh echo start `date` DK_LOG_DIR=./log DK_USR=dkggapp01 DK_PWD=dkggapp01 DK_SID=${ORACLE_SID} DK_OUT_FILE=dk_grp_insert.txt sqlplus -s ${DK_USR}/${DK_PWD}@${DK_SID} << EOF > ${DK_LOG_DIR}/${DK_OUT_FILE} whenever sqlerror exit sql.sqlcode insert into DKZT_GRP ( ******************************* GRP_CD , GRP_MEI_KNJ , GRP_MEI_KNA , GRP_RYS_KNJ , GRP_RYS_KNA , GRP_KNR_KBN_CD , GRP_HJI_KHI_FLG , GRP_HJI_JNJ , BSO_CD , RRI_DEL_FLG , ******************************1 DB_RGS , DB_TRK_D , DB_TRK_JKK , DB_KSS , DB_KSN_D , DB_KSN_JKK, DB_TMP , DB_KSN_GAM_ID ) values ( ******************************* '0123456', '東京センター', 'トウキョウセンター', '営業G', 'エイギョウ', '1', '1', '', '000', '0', ******************************2 'rinji', to_char(systimestamp, 'yyyymmdd'), to_char(systimestamp, 'hh24miss'), 'rinji', to_char(systimestamp, 'yyyymmdd'), to_char(systimestamp, 'hh24miss'), to_char(systimestamp, 'yyyymmddhh24missff3'), 'DK9999B9001' ) ; commit; exit; EOF # 終了判定 DK_RET=$? if [ ${DK_RET} -ne 0 ] then echo 異常終了 ステータス=${DK_RET} exit ${DK_RET} fi echo finish `date` exit ${DK_RET} ***2の部分を外部ファイルに書き込んでおき ***1へ代入するにはどうすれば良いでしょうか? 何を書いたらよいのかわからないので全て書いたつもりですが 足りない情報があったらご指摘いただけますと幸いです。 よろしくお願いいたします。

  • SQL文のEXISTSについて

    DBはmysql5.0を使っています。 以下のSQL文を、EXISTSを境に2つに分解することはできないでしょうか?? SELECT ROUND(SUM(IFNULL(T.DAIKIN,0) - IFNULL(T.TESURYO,0))/10000,1) INTO v_PRICE2 FROM TORIHIKI AS T WHERE T.TORIHIKI_KBN = '1' AND EXISTS (SELECT * FROM TORIHIKI AS T2 WHERE T2.TORIHIKI_DATE >= F_DATE AND T2.TORIHIKI_DATE <= T_DATE AND T2.TORIHIKI_KBN = '2' AND T2.KEHAI_CD = LPAD(v_SOBA_CD,5,'0') AND T2.KAIIN_SBT = v_KAIIN AND T.SEIRI_NO = T2.SEIRI_NO AND ROUND((IFNULL(T2.DAIKIN,0) + IFNULL(T2.TESURYO,0))/10000,1) >= p_MIN AND ROUND((IFNULL(T2.DAIKIN,0) + IFNULL(T2.TESURYO,0))/10000,1) < p_MAX );

  • PL/SQLの動的SQLで複数の項目を取得する方法教えて下さい。

    動的SQLで複数の項目を取得する方法で 悩んでいます。 下記の例だと、1項目しか取れません。 何か他のやり方でもいいので、複数の項目を 取得する方法を教えていただきたいです。 ********************************************* declare sql_stmt varchar2(200); wk_grp varchar2(5); wk_name varchar2(30); type cursor_type is ref cursor; cur_name cursor_type; begin wk_grp := '1u'; open cur_name for 'select 名前 from 社員表 where 所属グループ = :v1' using wk_grp; loop fetch cur_name into wk_name; exit when cur_name%notfound; dbms_output.put_line(wk_name); end loop; close cur_name; end; ********************************************* 下記のようなDBMS_SQLパッケージ?? を利用した方法がいいんでしょうかね。。。。 DBMS_SQL.COLUMN_VALUE(SQL,1,WK_NAME) DBMS_SQL.COLUMN_VALUE(SQL,2,WK_NO) よくわかってないので、宜しくお願いします。

  • 仮定の文章(皮質中のIEG発現について)

    We postulate that this likely reflects a top-down influence on IEG activation because the lower elevation of IEG expression in cortex of group NM, which was no greater than that associated with memory retrieval, was commensurate with that group being unable to incorporte new PAs into a nonexistent cortical schema. という文章がありどういう箇所で区切って訳せばいいのかちんうんかんぷんです。 どこで文章が切れていてどこまでがつながっているのかを解説していただければ幸いです。

  • 503エラーを回避したい

    先日、RSSを取得し、表示するPHPサイトを作ったのですが、アクセスのピーク時間になると503エラーが出ます。 アクセス数が原因?と思うのですが、対策方法がよく分かりません。原因もよくわかっていません。 最大アクセス数は[5000PV/1時間]程度です。 さくらのレンタルサーバ「ライトプラン」を使用しています。 ディスクの使用量[30MB / 1000MB(3%)] ウェブ転送量[548.6 MB(昨日)] エラーを回避したいのですがどうすればいいのでしょう? よろしくお願いします。

    • ベストアンサー
    • PHP
  • エラーが回避出来ません。

    WIN95の環境です。 ある特定のexeファイル(今のところ2つ)を実行すると以下のメッセージがでます。 再起動しても、常駐ファイルをはずしても、回避できません。 何か、対策知っている方今したら宜しくお願いします。 SETUP の 0による除算エラーです。 モジュール : MSVFW32.DLL、アドレス : 0137:7d425647 (以下省略) 起動出来ないソフトとしては、JW_winというフリーのソフトとサウンドボードのセットアップユーティリティです。