トリガーによるテーブル操作に制約がある理由とは?

このQ&Aのポイント
  • トリガーを使用して自分自身のテーブルを操作することはできません。
  • トリガーを使用してテーブルに行を挿入するときには、そのテーブル内の行を削除することはできません。
  • これは、無限ループやデータの一貫性を保つための制約です。
回答を見る
  • ベストアンサー

トリガって、自分自身のテーブルを操作することはできない?

あるテーブルに行を挿入すると、そのテーブルの1分前以上に挿入された 行を全て削除するようなトリガーの作成は可能でしょうか? トリガーは作れましたが、そのテーブルに行を挿入すると、 > Can't update table 'submitted' in stored function/trigger because it is already used by statement which invoked this stored function/trigger. といわれます。 トリガって、自分自身のテーブルを操作することはできないんですか? 例えば、table_a に行を挿入すると、table_a に行を挿入するトリガーを 作るのは、無限ループになるので駄目なのは分かります。 でも、table_a に行を挿入すると、table_a のある行を削除するトリガーも 作れないようですがどうしてでしょう?

  • MySQL
  • 回答数1
  • ありがとう数2

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

  • ベストアンサー
回答No.1

マニュアルに以下の記載があります。 「ストアド ファンクションまたはトリガ内では、その関数やトリガを実行したステートメントが ( 読み取り、または書込みに ) すでに使用しているテーブルを改変することはできない。」 http://dev.mysql.com/doc/refman/5.1/ja/routine-restrictions.html 理由としてはsweepeaさんが考えているように、SQL実行とトリガ実行が無限に繰り返される可能性があり、現状、再帰呼び出しも実装されていないので、入り口で禁止にしているということでしょう。

sweepea
質問者

お礼

ご回答ありがとうございます。 むー、なるほど。 ということは、INSERT時に古いデータを自動削除、みたいなことは できないんですね。 ※INSERT→トリガー→ストアドプロシージャ→DELETEとしても、 やはり無理でした。。。 MySQLが駄目なのか、僕のやろうとしてることが駄目なのか。。。 くやしいです。 どうも、ありがとうございました。

関連するQ&A

  • トリガが設定されたMySQL5.5準同期

    MySQL5.5の準同期レプリケーションを使って、マスターサーバー(insert用)とスレーブサーバー(select用)を組み合わせたサイトを作る予定です。 マスター側のサイトはトリガーとイベントを多用しております。(トリガー13個、イベント8個) 当初、マスター側にもスレーブ側にもどちらにもトリガーとイベントを組み込んでいましたが、テストして分かったことは、イベントがエラーを起こすということでした。 マスター側でイベントが始まり結果をスレーブ側に送ることになるわけですが、同時間にスレーブ側のイベントも始まるわけなので、マスターの結果が送られてきたときにはスレーブのテーブルには計算後の数値が記載されており、結果エラーになってしまうことがわかりました。 そのため、スレーブ側のイベントは削除して構築しています。 問題はトリガーについてです。 マスター側にはAテーブルにインサートするとBテーブル、Cテーブル、Dテーブルが連鎖的に変更されるトリガを組んでおり、スレーブ側も同様のトリガを組んでいます。 幸い、いままでのテストでは、トリガーで計算した値が連鎖的に伝わってもエラーになっていません。 ただ、マスター側に高負荷が掛かり、マスターのトリガの計算よりもスレーブ側の計算のほうが早く終了した場合、イベントの時に起こったエラーが出ないか懸念しています。 テストで壊れるのはいいですが、実際に運用した後で壊れることは許されません。 質問としては、「実際にトリガーを使った高負荷サイトを構築されている方でスレーブサーバーを準同期で設定している方」から、どのように組めばよいかのアドバイスを頂きたいというものです。(こんな高負荷サイトで運用しているがトリガを組んでて問題ないなどという例があるとうれしいです) よろしくお願いいたします。 スレーブのトリガーを外すのが一番簡単な方法なのですが、万一マスターがハングアップした際にはスレーブを昇格させる予定ですので出来る限りトリガーはそのままにしたいと考えておりますが、スレーブ側にトリガを組んだままというのは常識的にあり得ないというアドバイスであればそれでも結構です。 これはお願いなのですが、「他のサイトを調べて回答する」という方は申し訳ございませんがご遠慮願います(私も簡単なテストは済ませており低負荷では問題が生じないことまでは分かっております。ブログに落ちているような経験値はこれと大差ありません。この程度ではアドバイスにならないと感じています。) 実際に運用経験があり、正確な知識をお持ちの方にアドバイス頂きたいと思います。 よろしくお願いいたします。 構成はCentOS 6.3 MySQL 5.5.28です。

    • ベストアンサー
    • MySQL
  • トリガ実行時のエラー (ADP + MSDE2000)

    ADP + MSDE2000 環境にて、あるテーブルに下記のトリガを設定しました。 CREATE TRIGGER トリガ名 ON テーブル1 FOR DELETE  AS  BEGIN   DECLARE @変数 varchar(32)   SELECT @変数 = 列1 FROM deleted   DELETE FROM テーブル2   WHERE テーブル2.列1 = @変数  END 意図するところは、別のテーブル (テーブル2) からの同一キー (列1) を持つレコードの連動削除です。 このトリガを仕込んだテーブルに対してADPのGUI (テーブルのデータシートビュー) より手動にて直接 レコード削除を試みると、 「キー列の情報が足りないか、正しくありません。更新の影響を受ける行が多すぎます。」 のエラーが発生します。 (データシートビューを一度閉じた後、再度開くと、意図したレコードは消えています) GUIを使用せず、DELETE文で削除した場合、このエラーは出ず、動作結果も意図通りなのですが、前述の エラーは無視してよいものでしょうか? トリガの記述で問題点、改善すべき箇所があれば、ご指摘頂けると幸いです。 尚、このテーブルには、この他に3つのトリガが記述されています。 (できれば1本にまとめたいのですが、力量不足 + 時間不足です) 字数制限の関係で、書けませんが、他のトリガとの兼ね合いで問題が生ずることはあり得るのでしょうか? コメントをお待ちしております。

  • トリガからストアド実行について

    あるテーブルに追加処理を行った場合、ストアドを実行を実行したく、 トリガを作成してみましたが、 『トランザクションはトリガーで終了しました。バッチは中止されました。』という エラーが出てしまい困っています。 エラー内容で検索してもあまり出てこないので、 初歩的且つ、根本的に間違っているかと思うのですが、 初めて作成した為、なにがいけないのかも検討がつかない為、 ご教示頂きたく、投稿させて頂きます。 ○トリガ ALTER TRIGGER [dbo].[TRIG_SEND_MAIL] ON [dbo].[SEND_MAIL_INFO] FOR INSERT AS begin EXEC dbo.mail_test end ○目的としては対象テーブルを実行するとトリガを発動し、【dbo.mail_test】を起動させたい insert into SEND_MAIL_INFO (PROFILE_NAME,SEND_FLG) values ('AAAAAA','0') 上記SQL文を実施するとエラーなってしまいますので どうすればよいのか具体的な対処方法をご教示頂きたく、 何卒宜しくお願い申し上げます。

  • プロシージャとトリガー

    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 ; こんな感じでしょうか?

  • javascript でテーブル操作

    javascriptのdeleteRowで削除したテーブルの行を再表示する方法を探しております。 下記ソース内reload.gifをクリックするとdeleteRowで消えた行をまとめて表示したいのですが何か良い方法は無いでしょうか? (*)ブラウザの再表示は使えません。 <html> <head> <title></title> <script language="JavaScript" type="text/JavaScript"><!-- function Delline(tablename,num){ document.getElementById (tablename).deleteRow(num); } //--></script> </head> <body> <img src="reload.gif"> <table id="table1"> <tr onmouseover="asrow1 = this.rowIndex"> <td class="ChkTD41">ああ<img src="del.gif" onclick="Delline('table1',asrow1)" /> <input type="text" name="a1"> </td> </tr> <tr onmouseover="asrow2 = this.rowIndex"> <td class="ChkTD41">いい<img src="del.gif" onclick="Delline('table1',asrow2)" /> <input type="text" name="b1"> </td> </tr> <tr onmouseover="asrow3 = this.rowIndex"> <td>うう<img src="del.gif" onclick="Delline('table1',asrow3)" /> <input type="text" name="c1"> </td> </tr> </table> </body> </html>

  • テーブルの行操作について

    下記のJavaScriptの操作で質問があります。 ボタンを押すたびに1行目が最後に追加されていくと考えたのですが、 実際の動作では1行目が複製されず、行の入れ替えになってしまいます。 cloneNodeすれば行の追加になるのはわかりますが、なぜ下記の操作で行の入れ替えになるのでしょうか? <html> <head> <title>テーブルテスト</title> <script type="text/javascript"> <!-- function testFunction() { tableBody.appendChild(tableBody.childNodes(0)); } --> </script> </head> <body> <table border="1"> <thead> <tr><th>A</th><th>B</th><th>C</th></tr> </thead> <tbody id="tableBody"> <tr><td>foo</td><td>bar</td><td>hoge</td></tr> <tr><td>abc</td><td>def</td><td>ghij</td></tr> </tbody> </table> <input type="button" value="テスト" onclick="testFunction()" /> </body> </html>

  • 【html】tableでの奇数行と偶数行の色分けについて

    【html】tableでの奇数行と偶数行の色分けについて 【html】tableでの奇数行と偶数行の色分けについて 現在tableの奇数行と偶数行を以下のように色分けしているのですが、 これだとrowspanを利用したとき、画像1のようにずれてしまいます。 $(document).ready(function(){  $("table").each(function(){   jQuery(this).find("tr:even").addClass("even");  }); }); この状態を画像2のようにしたいのですが、どのようにすれば出来るでしょうか? よろしくお願いします。 ※画像小さくてすみません。

    • ベストアンサー
    • HTML
  • ピボットテーブルのことです

    ピボットテーブルで集計した表を作りました。 A列内で、例えばA6セルの右下をドラッグして下にずらすと「数式1」と入って行が挿入されてしまいました。 フィールドが追加されてしまったようですが、削除するにはどうしたらよいでしょうか? 宜しくお願いします。

  • 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にて実行は出来ました。 こちらもご存知の方お願いします。

  • アクセス テーブルデータ他のテーブルにコピーVBA

    win10 access365のmdbファイルにおいて table1のフィールド1がID 数値型 長整数型 値要求あり 重複あり フィールド2が氏名 短いテキスト型 225 値要求なし 重複あり  table2;フィールド1がID 数値型 長整数型 値要求あり 重複あり フィールド2が氏名 短いテキスト型 225 値要求なし 重複あり  上記に置いて table2の新しいデータとして table1のデータをコピーしたい、 ただしtable1には レコードは1行だけとします (table1にレコードが複数行ある場合の最新レコードだけtable2にコピーも出来れば知りたいです) アクセス付属の更新クエリーでは、どうも うまくいきません sqlにおいて UPDATE table1, table2 SET table2.ID = [table1]![ID], table2.氏名 = [table1]![氏名]; 上記動作しません Function table1から2() Dim db As DAO.Database Dim rst As Recordset Dim TB As Table Dim Rdset As Recordset On Error Resume Next Set db = DBEngine(0)(0) Set Rdset = db.OpenRecordset("table2", DB_OPEN_TABLE) Rdset.AddNew Rdset![ID] = Table![table1]![ID] Rdset![氏名] = Table![table1]![氏名] Rdset.Update End Function table1, table2を それぞれ 同名のフォームを作り Function table1から2() Dim db As DAO.Database Dim rst As Recordset Dim fm As Form Dim Rdset As Recordset On Error Resume Next Set db = DBEngine(0)(0) Set fm = Forms![table1] If Rdset.BOF Then Exit Function Else Set Rdset = db.OpenRecordset("table2", DB_OPEN_TABLE) Rdset.AddNew Rdset![ID] = Forms![table1]![ID] Rdset![氏名] = Forms![table1]![氏名] Rdset.Update End If End Function いずれも table2のデータ更新が なされていません すみません 宜しくお願い致します