2017-06-13 107 views
1

我正在使用時間戳列到我的表格之一,並使用自動更新功能。這裏是我的表模式:即使使用相同的列值,MySQL'timestamp'也要更新

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) 

什麼我期待的是,

  • created_at柱要與時間初始化,該行被創建和
  • updated_at列是與created_at相同,並且在更新任何列(基本上ride_cnt)時也會更新。

This works great。

但我也期待的是updated_at即使ride_cnt具有相同的值更新。這樣我就可以跟蹤上次訪問該行的值的時間,並可以將其忽略以供進一步運行。

例如:

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子句從未加入過。我可以爲您的問題提供兩種解決方法。第一個可能是性能最高的應該是在更新期間手動將updated_at列設置爲當前時間戳。因此,從上面的例子中,你會使用它代替:

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

這應該觸發行的實際更新,因爲自上次更新的時間戳已經改變。

另一個解決方法是找到一種方法來確保每次更新總是會更改給定記錄中的某些數據。然後,將始終應用ON UPDATE子句。

這可能看起來像一個限制,但我猜MySQL如果底層數據本身沒有改變,就不會考慮發生在記錄中的變化。

這個問題是排序此項目重複的:

How to Force UPDATE of MySQL Record When Nothing Is Changing

然而,由於SO的這個問題的範圍是如此之薄,我想這個答案可能是任何人都遇到相同的問題非常有用。

+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(); 

(對於那些想知道的DELIMITER指令是,他們沒有當觸發器有一個單一的,簡單的語句需要)。

+0

向上投票的分界符OP然而不能使用觸發器。查看評論。 – Namphibian

+0

@Nphphibian,謝謝。我忽略了這一點。 –

相關問題