MySQL TIPS 1 怪盗ロワイヤルのように3分に1ポイント回復
MySQLネタもそろそろ尽きてきたので、趣向を変えてMySQLの実践Tipを紹介していこうと思います。
まずは怪盗ロワイヤルのように3分に1ポイント回復する実装について以下のように3分に一度バッチを回して、全ユーザの体力を+1ずつアップデートするのは効率が悪いので、リアルタイムに計算する方法を考えます。
UPDATE `charactor` SET hp=IF((hp+1)>100,100,hp+1)
まずはテーブルやデータを準備
CREATE TABLE `charactor` ( `charactor_id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT 'キャラクターID', `hp` INT NOT NULL COMMENT 'HP', `max_hp` INT NOT NULL COMMENT '最大HP', `updated_time` TIMESTAMP( 11 ) NOT NULL COMMENT '更新日時' ) ENGINE = MYISAM COMMENT = 'キャラクターテーブル';
INSERT INTO `charactor` (`hp`,`max_hp`) VALUES ('56','124');
SQLでリアルタイムに演算
- SELECT時
-- 現在ヒットポイントの演算 SELECT if( max_hp < floor(hp + (unix_timestamp(now()) - unix_timestamp(updated_time) )/(60 * 3)), max_hp, floor(hp + (unix_timestamp(now()) - unix_timestamp(updated_time) )/(60 * 3)) ) as hp, max_hp FROM charactor WHERE charactor_id = 1
- UPDATE時
-- 現在ヒットポイントから減算 UPDATE charactor SET hp = if( max_hp < floor(hp + (unix_timestamp(now()) - unix_timestamp(updated_time))/(60 * 3)), max_hp, floor(hp + (unix_timestamp(now()) - unix_timestamp(updated_time))/(60 * 3)) ) - 5 WHERE charactor_id = 1
冗長なのでviewを作る(失敗編)
CREATE OR REPLACE ALGORITHM = MERGE VIEW `v_charactor` AS SELECT charactor_id , IF( max_hp < floor( hp + ( UNIX_TIMESTAMP( NOW( ) ) - UNIX_TIMESTAMP( updated_time ) ) /(60 *3) ) , max_hp, floor( hp + ( UNIX_TIMESTAMP( NOW( ) ) - UNIX_TIMESTAMP( updated_time ) ) /(60 *3) ) ) AS hp, max_hp FROM charactor
UPDATE `v_charactor` SET hp=hp-5 WHERE charactor_id=1
#1348 - Column 'hp' is not updatable
....更新できませんね。
viewのマニュアルを見ると更新可能なviewの条件に入ってないのでそりゃ無理か。
ビューカラムは派生カラムではなく、単純なカラムリファレンスでなければなりません。派生カラムは単純なカラムリファレンスでなく、表現から派生したものです。
しょうがないので、トリガー*1で実現してみる。...続く