2017-06-13 12 views
1

私は自分のテーブルにタイムスタンプの列を使用し、自動更新機能を使用しています。私は何を期待してることは同じ列の値でも更新されるMySQLの `timestamp`

  • created_at列が時間とともに初期化されるように、ということである

    mysql> desc user_rides; 
    +------------+--------------+------+-----+-------------------+-----------------------------+ 
    | Field  | Type   | Null | Key | Default   | Extra      | 
    +------------+--------------+------+-----+-------------------+-----------------------------+ 
    | id   | int(11)  | NO | PRI | NULL    | auto_increment    | 
    | user_id | int(11)  | NO | MUL | NULL    |        
    | ride_cnt | int(11)  | YES |  | NULL    |        | 
    | created_at | timestamp | NO |  | CURRENT_TIMESTAMP |        | 
    | updated_at | timestamp | NO |  | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP | 
    +------------+--------------+------+-----+-------------------+-----------------------------+ 
    5 rows in set (0.02 sec) 
    

    、行が作成されると

  • updated_at列であるために:ここに私のテーブルスキーマですcreated_atと同じであり、いずれかの列(基本的にはride_cnt)が更新されると更新されます。

これは素晴らしいです。

でも、ride_cntが同じ値を持っていてもupdated_atが更新されることが予想されます。そこで、行の値が最後にフェッチされた時点を追跡して、それ以降の実行を無視することができます。例えば

ride_cnt = 0と

行は、我々は、更新を実行した最新の時刻で更新します。行が無視されて再初期化されることがあります。

タイムスタンプを手動で渡すことなくこれを達成できる方法はありますか?

編集:何が起こっている。ここ

mysql> insert into user_ride set user_id=7445, user_ride=0; 
Query OK, 1 row affected (0.01 sec) 

mysql> insert into user_ride set user_id=7009, user_ride=2; 
Query OK, 1 row affected (0.00 sec) 

mysql> select * from user_ride; 
+----+---------+-----------+---------------------+---------------------+ 
| id | user_id | user_ride | created_at   | updated_at   | 
+----+---------+-----------+---------------------+---------------------+ 
| 1 | 7445 |   0 | 2017-06-13 10:44:05 | 2017-06-13 10:44:05 | 
| 2 | 7009 |   2 | 2017-06-13 10:44:18 | 2017-06-13 10:44:18 | 
+----+---------+-----------+---------------------+---------------------+ 
2 rows in set (0.00 sec) 

mysql> update user_ride set user_ride=0 where id=1; 
Query OK, 0 rows affected (0.01 sec) 
Rows matched: 1 Changed: 0 Warnings: 0 

mysql> select * from user_ride; 
+----+---------+-----------+---------------------+---------------------+ 
| id | user_id | user_ride | created_at   | updated_at   | 
+----+---------+-----------+---------------------+---------------------+ 
| 1 | 7445 |   0 | 2017-06-13 10:44:05 | 2017-06-13 10:44:05 | 
| 2 | 7009 |   2 | 2017-06-13 10:44:18 | 2017-06-13 10:44:18 | 
+----+---------+-----------+---------------------+---------------------+ 
2 rows in set (0.00 sec) 

mysql> update user_ride set user_ride=1 where id=1; 
Query OK, 1 row affected (0.01 sec) 
Rows matched: 1 Changed: 1 Warnings: 0 

mysql> select * from user_ride; 
+----+---------+-----------+---------------------+---------------------+ 
| id | user_id | user_ride | created_at   | updated_at   | 
+----+---------+-----------+---------------------+---------------------+ 
| 1 | 7445 |   1 | 2017-06-13 10:44:05 | 2017-06-13 10:45:26 | 
| 2 | 7009 |   2 | 2017-06-13 10:44:18 | 2017-06-13 10:44:18 | 
+----+---------+-----------+---------------------+---------------------+ 
2 rows in set (0.00 sec) 
+0

トリガーを試しましたか? – Namphibian

+1

レコード内の同じ値を使用して更新すると、更新が行われ、現在のタイムスタンプは更新されます。私はここに何かを逃していますか –

+0

@TimBiegeleisen、私も同じと思っていましたが、そうではありません。追加された例。 – avisheks

答えて

2

私はあなたが上記のシナリオでは、あなたの最初の更新に注意を喚起したい:

mysql> update user_ride set user_ride=0 where id=1; 
Query OK, 0 rows affected (0.01 sec) 
Rows matched: 1 Changed: 0 Warnings: 0 

我々があったことがわかります一致する行はありますが、実際には更新は行われませんでした。この理由は、更新によって実際にデータが変更されなかったためです。したがって、updated_atタイムスタンプのON UPDATE句は蹴られませんでした。あなたの問題の2つの回避策を提供できます。最初の、おそらく最も性能の高いものは、更新中に手動でupdated_at列を現在のタイムスタンプに手動で設定するだけです。したがって、たとえばからあなたの代わりにこれを使用する上:

update user_ride set user_ride = 0, updated_at = CURRENT_TIMESTAMP where id=1; 

これを、最後に更新されたため、タイムスタンプが変更されたため、行の実際の更新をトリガする必要があります。

もう1つの回避策は、各更新が常に指定されたレコードの一部のデータを変更する方法を見つけることです。次に、ON UPDATE句が常に適用されます。

これは制限のように思えるかもしれませんが、基本データ自体が変更されなかった場合、MySQLはレコードに変更が加えられたとみなさないと思います。

この質問はこの1つの複製の一種である。この問題のSOのカバレッジが、私はこの答えは同じ問題に遭遇した他の誰にも役に立つかもしれないと思ったので、薄いので、しかし

How to Force UPDATE of MySQL Record When Nothing Is Changing

+0

ありがとうTim、これは暗黙のうちにどんな意味でも達成できるかどうかを知りたかったのです。手動でタイムスタンプを渡すことは、私が考えることができるより良い解決策ですが、私たちがmysqlの自動更新機能を利用できない場合、悪い点です。その場合に 'ON UPDATE'節を追加する意味はありません:) – avisheks

+0

@avisheksはい、' ON UPDATE'の意味です。これは、レコード内の実際のデータが変更されたことを意味し、発生したときにタイムスタンプのみを変更したい場合があります。あなたの特別なケースでは、あなたが望むものではありません。 –

+0

それは、私の場合はないです。 – avisheks

1

トリガを追加します。

CREATE TRIGGER user_ride_bu 
BEFORE UPDATE ON user_ride 
FOR EACH ROW 
SET NEW.updated_at = NOW(); 

(トリガーが1つの単純な文を持っているときDELIMITERディレクティブがどこにあるか疑問に思う方のために、彼らは必要ありません)。

+0

区切り文字のためにUpvotedしかしOPはトリガーを使用することができません。コメントを参照してください。 – Namphibian

+0

@親生類、ありがとう。私はそれを見落とした。 –

関連する問題