mysql5.7 ПРИ обновлении синтаксиса ДУБЛИКАТА КЛЮЧА обновит дополнительный столбец

#mysql #go

#mysql #Вперед

Вопрос:

синтаксис mysql5.7 «ПРИ ОБНОВЛЕНИИ ДУБЛИКАТА КЛЮЧА» обновит дополнительный столбец, даже если вы не обновили

используйте ‘insert … ПРИ ОБНОВЛЕНИИ ДУБЛИКАТА КЛЮЧА …’ чтобы обновить some_data = ЗНАЧЕНИЯ (some_data), он также обновляет столбец created_at

 result, err := DB.Exec("INSERT INTO `test_duplicate_key_bug_table`(some_data,created_at) VALUES(?,?)", "test data", createdAt)
    require.NoError(t, err)
    id, err := result.LastInsertId()
    require.NoError(t, err)
    // mysql's timestamp only storage second's level date, re-find it's real datetime
    row := DB.QueryRow("SELECT created_at FROM `test_duplicate_key_bug_table` WHERE id=? LIMIT 1", id)
    var oldCreatedAt time.Time
    err = row.Scan(amp;oldCreatedAt)
    require.NoError(t, err)

    result, err = DB.Exec("INSERT INTO `test_duplicate_key_bug_table`(id,some_data,created_at) VALUES(?,?,?) ON DUPLICATE KEY UPDATE some_data = VALUES(some_data)", id, "test data again", time.Now())
    require.NoError(t, err)

    row = DB.QueryRow("SELECT some_data,created_at FROM `test_duplicate_key_bug_table` WHERE id=? LIMIT 1", id)
    var newCreatedAt time.Time
    var newData string
    err = row.Scan(amp;newData, amp;newCreatedAt)
    require.NoError(t, err)

    fmt.Printf("old time %s n", oldCreatedAt)
    fmt.Printf("new time %s n", newCreatedAt)
    fmt.Printf("new data %s n", newData)
  

вывод:

 old time 2019-04-12 03:29:17  0000 UTC 
new time 2019-04-12 03:29:27  0000 UTC 
new data test data again 
  

но только обновите id = VALUES (id), он работает хорошо

 result, err := DB.Exec("INSERT INTO `test_duplicate_key_bug_table`(some_data,created_at) VALUES(?,?)", "test data", createdAt)
    require.NoError(t, err)
    id, err := result.LastInsertId()
    require.NoError(t, err)
    // mysql's timestamp only storage second's level date, re-find it's real datetime
    row := DB.QueryRow("SELECT created_at FROM `test_duplicate_key_bug_table` WHERE id=? LIMIT 1", id)
    var oldCreatedAt time.Time
    err = row.Scan(amp;oldCreatedAt)
    require.NoError(t, err)

    result, err = DB.Exec("INSERT INTO `test_duplicate_key_bug_table`(id,some_data,created_at) VALUES(?,?,?) ON DUPLICATE KEY UPDATE id = VALUES(id) ", id, "test data again", time.Now())
    require.NoError(t, err)

    row = DB.QueryRow("SELECT some_data,created_at FROM `test_duplicate_key_bug_table` WHERE id=? LIMIT 1", id)
    var newCreatedAt time.Time
    var newData string
    err = row.Scan(amp;newData, amp;newCreatedAt)
    require.NoError(t, err)

    fmt.Printf("old time %s n", oldCreatedAt)
    fmt.Printf("new time %s n", newCreatedAt)
    fmt.Printf("new data %s n", newData)
  

вывод:

 old time 2019-04-12 03:29:17  0000 UTC 
new time 2019-04-12 03:29:17  0000 UTC 
new data test data 
  

Я использую mysql от docker

полный пример кода

Я предполагаю, что это «github.com/go-sql-driver/mysql » проблема с водителем

Комментарии:

1. Пожалуйста, добавьте определение вашей таблицы (вывод show create table test_duplicate_key_bug_table ). Возможные причины такого поведения в порядке вероятности: a) ваш created_at столбец определен с помощью on update current_timestamp (который, как ожидается, будет вести себя точно так, как вы описываете, если id это первичный ключ) б) вы включили explicit_defaults_for_timestamp в своей конфигурации в) у вас есть on update триггер в вашей таблице, который устанавливает этот столбец d-y) (z)ошибка в драйвере.

2. @Solarflare да, столбец created_at имеет ПРИ ОБНОВЛЕНИИ атрибут CURRENT_TIMESTAMP, спасибо