トリガで複数行のインサートを実行したい

このQ&Aのポイント
  • mysql 5.5.16で、全体ユーザーから誕生日が来た人だけを選別する仕組みを作っています。
  • userテーブルには1000人の19才ユーザーが配置されています。このリストから「20才の誕生日が着たら20yearsテーブルに複写させる」ことを考えました。
  • アドバイスを頂けましたら幸いです。尚、ニーズは誕生日が来たユーザーだけを移動することですので、私の発案の方法に限らずもっといい方法があればアドバイスをお願いいたします。
回答を見る
  • ベストアンサー

トリガで複数行のインサートを実行したい

mysql 5.5.16で、全体ユーザーから誕生日が来た人だけを選別する仕組みを作っています。 テーブル user (id_1 INT, user_1 TEXT,count_1 INT,nextbirthday_1 DATETIME) テーブル 20years (id_2 INT, user_2 TEXT,nextbirthday_2 DATETIME) userテーブルには1000人の19才ユーザーが配置されています。 このリストから「20才の誕生日が着たら20yearsテーブルに複写させる」ことを考えました。 まずは、EVENT でrecordにある1000人のユーザー全ての count_1 を毎日1回づつUPDATEさせます。 このアップデートをTRIGGERとして、誕生日と現在時間を見合わせ、誕生日が現在時間より古いユーザーは(誕生日が来たものは)20yearに複写させることを考えました。 その案が下記のEVENT とTRIGGERです。 ******************************** CREATE EVENT happybirthday ON SCHEDULE EVERY 1 DAY STARTS '2012-04-25 09:00:00' ENDS '2013-03-31 09:00:00' DO UPDATE record SET count_1 = count_1 + 1; ******************************** DELIMITER // CREATE TRIGGER 20_trigger AFTER UPDATE ON record FOR EACH ROW BEGIN IF(SELECT NEW.nextbitthday_1 <= NOW()) THEN INSERT INTO 20years SET id_2=NEW.id_1,user_2=NEW.user_1,nextbirthday_2=NEW.nextbirthday_1 ON DUPLICATE KEY UPDATE id_2=NEW.id_1; END IF; END; // DELIMITER ; ******************************** FOR EACH ROW BEGIN で全てのユーザーの誕生日を見に行き、誕生日に4人が該当すれば4人が20yearsに複写されるはずです。 しかし実際には、該当する一番上の一人だけしか複写させることが出来ませんでした。 (本日誕生日のユーザーが4人いて、4/16以前が誕生日の人が10人いた場合、それら合計14人のうち、userテーブル上で一番上に位置するユーザーだけが複写される) このトリガの書き方では、FOR EACH ROW BEGINと設定しているにも関わらず、全てのユーザーに対してトリガ作業を行わず、上から一人目を抽出した時点で作業を終了しているようです。 アドバイスを頂けましたら幸いです。 尚、ニーズは誕生日が来たユーザーだけを移動することですので、私の発案の方法に限らずもっといい方法があればアドバイスをお願いいたします。 追伸 IF節を全て外しても同様に一人しか抽出しませんでしたので、IF節が悪さをしている訳ではないようです。 よろしくお願いいたします。

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

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

  • ベストアンサー
  • mpro-gram
  • ベストアンサー率74% (170/228)
回答No.1

INSERT INTO では set での構文は一行insert 用です。 INSERT INTO `tablename` select .. でuser tableから必要な行を選択して流し込めば、複数行insertできる。

tajix14
質問者

お礼

有難うございます。 ご指摘いただいた方法で対応できました!! INSERT INTO では set での構文は一行insert 用ということを知らず長時間悩んでいました。 有難うございました。本当に助かりました!

その他の回答 (1)

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

EVENTで当日の誕生日の人を一括して「20years」にINSERTして、DELETEするのはどうですか。

tajix14
質問者

お礼

アドバイス有難うございます。 確かにご指摘の方法であれば、無駄にカウントアップしていく必要がありませんね。 勉強になります。 この方法についてもトライしてみます。 有難うごさいました。

関連するQ&A

  • phpmyadminはトリガーやIF文を使えますか

    mysql> delimiter $$ mysql> create trigger trigger_update after update on user for each row -> begin -> update address set name = new.name where name = old.name; -> end; -> $$ mysql> delimiter ; こちらをphpmyadminでどのようにしたら使うことができますか。

    • ベストアンサー
    • MySQL
  • 特定カラム値が規定値以上になった場合発動するトリガ

    MySQLのトリガについて教えてください。 投票システムを作っています。 テーブル名 abc ( abc1_id(プライマリ) , abc2_vote_volume(INT) ) テーブル名 def ( def1_id(プライマリ) , def2_vote_volume(INT) ) があります。 テーブル名 abc にある abc2_vote_volume(INT)にはユーザーが1票づつ投票します。 abc2_vote_volume(INT)が49までのうちは何も起こらず、 abc2_vote_volume(INT)が50を超えたら「テーブル名 def 」に全てをコピーしていくトリガの作成を考えました。 私が考えたのは下記の表現なのですが、エラーとなります。 FOR AS IF UPDATE 49<NEW.adc2_vote_volume が見るからに怪しいのですが、改定方法が分かりません。 詳しい方、ご教授頂けますようお願いいたします。 DELIMITER // CREATE TRIGGER a_ref AFTER UPDATE ON abc FOR AS IF UPDATE 49<NEW.adc2_vote_volume INSERT INTO def SET def1_id =NEW.abc1_id,abc2_vote_volume=NEW.abc2_vote_volume ON DUPLICATE KEY UPDATE def1_id =NEW.abc1_id,abc2_vote_volume=NEW.abc2_vote_volume; END; // DELIMITER

    • ベストアンサー
    • MySQL
  • TRIGGERの書き方について

    MYSQLで株の履歴を作っています。 テーブルとしては、株を購入するユーザー書き込み用のa_nowstock、書き込み履歴を記録するa_nowstock_history、最新の保有株を記録するa_lateststockとなります。 テーブル a_nowstock    (a1_id(自動取得),a2_user_id,a3_usr_volume,a4_latest_volume) a_nowstock_history(b1_id(自動取得),b2_user_id,b3_usr_volume) a_lateststock (d1_id(自動取得),d2_user_id,d3_latest_volume) a_nowstock はユーザーが書き込むテーブル a_nowstock_historyは書き込み履歴 a_lateststockは最新保有情報のみのデータとなります。 これをTRIGGERで処理するために下記のようにSQLで指示してみました。 DELIMITER // CREATE TRIGGER a_ref BEFORE INSERT ON a_nowstock FOR EACH ROW BEGIN INSERT INTO a_nowstock_history SET b2_usr_id = NEW.a2_usr_id, b3_usr_volume = NEW.a3_usr_volume; UPDATE INTO a_lateststock SET d2_usr_id = NEW.a2_usr_id, d3_latest_volume = NEW.a4_latest_volume; END; // DELIMITER ; しかしながら #1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near INTO a_lateststock SET d2_usr_id = NEW.a2_usr_id, d3_latest_volume = NEW.a4_latest_volume; ' at line 5 というエラーが出てしまいます。 DELIMITER // CREATE TRIGGER a_ref BEFORE INSERT ON a_nowstock FOR EACH ROW BEGIN INSERT INTO a_nowstock_history SET b2_usr_id = NEW.a2_usr_id, b3_usr_volume = NEW.a3_usr_volume; END; // DELIMITER ; のように、INSERT INTO だけだと問題なく作動するため、UPDATEがうまくいっていないようです。 TRIGGERはUPDATEも機能するはずなのですが、うまくいきません。 アドバイスいただけましたら幸いです。 よろしくお願いいたします。

    • ベストアンサー
    • MySQL
  • TRIGGERの書き方について 再質問

    以前質問したものです。解決したと思っていたのですが、エラーが無くなただけで解決はしてませんでしたので再度質問いたします。 MYSQLで株の履歴を作っています。 テーブルとしては、株を購入するユーザー書き込み用のa_nowstock、書き込み履歴を記録するa_nowstock_history、最新の保有株を記録するa_lateststockとなります。 テーブル a_nowstock    (a1_id(自動取得),a2_user_id,a3_usr_volume,a4_latest_volume) a_nowstock_history(b1_id(自動取得),b2_user_id,b3_usr_volume) a_lateststock (d1_id(自動取得),d2_user_id,d3_latest_volume) a_nowstock はユーザーが書き込むテーブル a_nowstock_historyは書き込み履歴 a_lateststockは最新保有情報のみのデータとなります。 これをTRIGGERで処理するために下記のようにSQLで指示してみました。 DELIMITER // CREATE TRIGGER a_ref BEFORE INSERT ON a_nowstock FOR EACH ROW BEGIN INSERT INTO a_nowstock_history SET b2_usr_id = NEW.a2_usr_id, b3_usr_volume = NEW.a3_usr_volume; UPDATE a_lateststock SET d2_usr_id = NEW.a2_usr_id, d3_latest_volume = NEW.a4_latest_volume; END; // DELIMITER ; これでトリガーを登録すると、エラーは出ないのですが、実際に a_nowstock に入力してみると、a_nowstock_historyには反映されるものの、a_lateststock には何も反映されません。 調べてみてもTRIGGERの中でUPDATEする方法が見当たらず途方に暮れています。 詳しい方、大変恐縮ですがアドバイス願います。

    • ベストアンサー
    • MySQL
  • 複数行コピー、貼り付け実行時エラー1004

    ユーザー側が任意の場所を選択コピー し(2行毎) また 任意の位置に貼り付ける動作ですが 1回目のコピー、貼り付けは正常動作しますが 再度 コピー(任意の場所),貼り付け時に1004実行エラーが発生します。 下記はコードです。 どうかご教授お願いいたします。 Dim StartRow As Long, LastRow As Long, SRC As Long Sub コピー() If ActiveCell.Row < 76 Then Exit Sub StartRow = ActiveCell.Row: SRC = Selection.Rows.Count If (ActiveCell.Row Mod 2) = 0 Then StartRow = ActiveCell.Row If (Selection.Rows.Count Mod 2) = 0 Then LastRow = StartRow + Selection.Rows.Count - 1 Else LastRow = StartRow + Selection.Rows.Count End If Else StartRow = ActiveCell.Row - 1 If (Selection.Rows.Count Mod 2) = 0 Then LastRow = StartRow + Selection.Rows.Count + 1 Else LastRow = StartRow + Selection.Rows.Count End If End If ActiveSheet.Range(ActiveSheet.Cells(StartRow, 1), ActiveSheet.Cells(LastRow, 19)).Copy End Sub Sub 貼付け() If ActiveCell.Row >= 76 Or Application.ClipboardFormats(1) <> -1 Then ActiveSheet.Unprotect If (ActiveCell.Row Mod 2) = 0 Then StartRow = ActiveCell.Row Else StartRow = ActiveCell.Row - 1 End If ActiveSheet.Paste Destination:=Cells(StartRow, 1): Application.CutCopyMode = False ActiveSheet.Protect End If End Sub

  • SymfoWareでトリガの作成

    SymfoWareでトリガを作成したいと思います。 CREATE TRIGGER トリガ名 AFTER INSERT ON 表1 REFERENCING NEW AS NEWREC FOR EACH ROW WHEN(条件)        INSERT INTO 表2 VALUES(NEWREC.項目名, NEWREC.項目名,…) となりますが、 WHENの条件に表1以外の表の値を持ってくることは できるのでしょうか? それから、表2にINSERTするVALUEの値も、表1以外のテーブル の値を取ってくることは可能でしょうか? よろしくお願いします。

  • TRIGGER上の足し算について

    MYSQLで株の履歴を作っています。 テーブルとしては、株を購入するユーザー書き込み用のa_nowstock、最新の保有株を記録するa_lateststockとなります。 テーブル a_nowstock    (a1_id(自動取得),a2_user_id,a3_buy_stock_volume) a_lateststock (d2_user_id(PRIMARY),d3_latest_volume) a_nowstock が入力されたら、最新数量を足し算してa_lateststockの中のd3_latest_volumeを更新します。 これをTRIGGERで処理するために下記のようにSQLで指示してみました。 DELIMITER // CREATE TRIGGER a_ref BEFORE INSERT ON a_nowstock FOR EACH ROW BEGIN INSERT INTO a_lateststock SET d2_usr_id = NEW.a2_usr_id, d3_latest_volume = NEW.a3_buy_stock_volume ON DUPLICATE KEY UPDATE d2_usr_id = NEW.a2_usr_id, d3_latest_volume = d3_latest_volume + NEW.a3_buy_stock_volume; END; // DELIMITER ; しかしながら、下記の通りエラーとなります。 #1054 - Unknown column 'd3_latest_volume ' in 'field list' d3_latest_volumeをold.d3_latest_volumeとして指示しても同様です。 #1054 - Unknown column 'old.d3_latest_volume ' in 'field list' WEB上のMySQL リファレンスマニュアルの記載(UPDATE persondata SET age=age+1;)を見る限り足し算は可能と考えています。 どこに問題があるか詳しい方ご教授頂けましたら幸いです。 どうぞよろしくお願いいたします。

    • ベストアンサー
    • MySQL
  • トリガに排他制御をかけたいのですが

    トリガに排他制御をかけたいのですが Oracleのトリガで、 トリガ内の処理に対して排他制御をおこないたいのですが、 どのように設定すればよいのでしょうか? トリガの内容は以下となります。 CREATE OR REPLACE TRIGGER TRI_TEST after update of (トリガの実行条件その1) on ORG_TBL FOR EACH ROW begin if (トリガの実行条件その2) THEN begin insert(実行される処理その1) EXCEPTION update(実行される処理その2) end; end if; end; / 上記の条件において、 「実行される処理その1」 「実行される処理その2」 を行っている最中に他からのアクセスをブロックをさせたく思っております。 本件の理由は 他からのアクセスで行われる処理が 「select(トリガによってデータが投入されてるテーブル)」 「truncate(トリガによってデータが投入されてるテーブル)」 を連続して行う処理のため、 排他を実行しなかった場合、 他からのアクセスの「select」と「truncate」の処理間に トリガによってレコードがinsertされた際に、 そのレコードがselectされなくなることを危惧しているためです。

  • トリガーについて

    このジャンルでお願いします。 次のようなテーブルで DROP TABLE IF EXISTS item; CREATE TABLE IF NOT EXISTS item ( id int(11) NOT NULL AUTO_INCREMENT, parent_id INT, name varchar(32) NOT NULL, level int NOT NULL, FOREIGN KEY (parent_id) REFERENCES item(id) ON DELETE CASCADE ON UPDATE CASCADE, PRIMARY KEY(id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO item (parent_id, name) VALUES (null, 'item1'); INSERT INTO item (parent_id, name) VALUES (1, 'item2'); INSERT INTO item (parent_id, name) VALUES (2, 'item3'); INSERT INTO item (parent_id, name) VALUES (3, 'item4'); INSERT INTO item (parent_id, name) VALUES (2, 'item5'); INSERT INTO item (parent_id, name) VALUES (null, 'item6'); INSERT INTO item (parent_id, name) VALUES (6, 'item7'); INSERT INTO item (parent_id, name) VALUES (null, 'item8'); DROP PROCEDURE IF EXISTS UPDATE_LEVEL; DELIMITER // CREATE PROCEDURE UPDATE_LEVEL() BEGIN DECLARE CNT INT; DECLARE LVL INT; SET LVL=1; UPDATE item SET level=0; UPDATE item SET level=LVL WHERE parent_id IS NULL; SELECT COUNT(*) INTO CNT FROM item WHERE level=LVL; WHILE CNT>0 DO UPDATE item INNER JOIN (SELECT id FROM item WHERE level=LVL) as temp ON parent_id=temp.id SET item.level=LVL+1; SET LVL=LVL+1; SELECT COUNT(*) INTO CNT FROM item WHERE level=LVL; END WHILE; END // DELIMITER ; DROP TRIGGER IF EXISTS TRG_INSERT_ITEM; DELIMITER // CREATE TRIGGER TRG_INSERT_ITEM AFTER INSERT ON item FOR EACH ROW BEGIN CALL UPDATE_LEVEL(); END; // DELIMITER ; itemテーブルにinsertした場合にトリガーでUPDATE_LEVEL()を実行するようにしているのですが、 実際に挿入すると、 >Can't update table 'item' in stored function/trigger because it is already used by statment which invoked this stored function/trigger . このようなエラーが出てしまいます・・・ UPDATE_LEVEL()にinsertらしき記述はないと思うのですが、 これはなぜこのようなエラーが出るのでしょうか?

    • ベストアンサー
    • MySQL
  • トリガーで計算させた値を履歴として記録するには

    株の購入履歴をトリガー内部で計算したいと考えています。 buying_stockの購入をすると、トリガーで最新の数量を計算しnow_stockテーブルに最新情報を記入、更新します。 テーブル ●buying_stock d1(プライマリ),d2_usr_id,d3_stock_id,d4_buy_stock_volume, ●now_stock f2_stock_id(プライマリ),f3_stock_name,f4_latest_stock_volume トリガ DELIMITER // CREATE TRIGGER a_ref0 BEFORE INSERT ON buying_stock FOR EACH ROW BEGIN INSERT INTO now_stock SET f2_stock_id=NEW.d3_stock_id,f3_stock_name=f3_stock_name,f4_latest_stock_volume=f4_latest_stock_volume+NEW.d4_buy_stock_volume ON DUPLICATE KEY UPDATE f2_stock_id=NEW.d3_stock_id,f3_stock_name=f3_stock_name,f4_latest_stock_volume=f4_latest_stock_volume+NEW.d4_buy_stock_volume; END; // DELIMITER ; ここまでは出来ました。 ただ、これでは最新価格は残りますが、購買履歴が残りません。 そこで、下記のトリガーを作成しました。 テーブル ●stock_history g1(プライマリ),g2_stock_id,g3_stock_name,g4_latest_stock_volume トリガー DELIMITER // CREATE TRIGGER a_ref000 BEFORE INSERT ON now_stock FOR EACH ROW BEGIN INSERT INTO stock_history SET g2_stock_id=NEW.f2_stock_id,g3_stock_name=NEW.f3_stock_name,g4_latest_stock_volume=NEW.f4_latest_stock_volume; END; // DELIMITER ; しかしながら、g3_stock_nameとg4_latest_stock_volumeがNULLになってしまいます。 古い購入履歴と最新の購入数は別物として捉えられているようです。 一方、同一のものとして指示するために、テーブルをg2_stock_id(プライマリ),g3_stock_name,g4_latest_stock_volumeとすると、Duplicate違反を指摘されます。 トリガーで計算した後の履歴を残すためにはどのような方法があるでしょうか? テーブルには ●stock_name a1(プライマリ),a2_stock_id,a3_stock_name, というものもございますので、これを使用すれば出来るのかもしれません。 ご指導いただきたくお願いいたします。

    • ベストアンサー
    • MySQL