MySQL: странное поведение запроса UPDATE (ОШИБКА 1062 Duplicate entry)

0

У меня есть база данных MySQL, где хранятся новостные статьи с датой публикации (только дневная информация), источником и категорией. Исходя из этого, я хочу сгенерировать таблицу, содержащую счетчик статей по этим 3 параметрам.

Поскольку для некоторых комбинаций этих трех параметров не может быть никакой статьи, простая GROUP BY не будет делать. Поэтому я сначала news_article_counts таблицу news_article_counts со всеми возможными комбинациями из 3 параметров и по умолчанию article_count 0 - вот так:

SELECT * FROM news_article_counts;
+--------------+------------+----------+---------------+
| published_at | source     | category | article_count |
+------------- +------------+----------+---------------+
| 2016-08-05   | 1826089206 |        0 |             0 |
| 2016-08-05   | 1826089206 |        1 |             0 |
| 2016-08-05   | 1826089206 |        2 |             0 |
| 2016-08-05   | 1826089206 |        3 |             0 |
| 2016-08-05   | 1826089206 |        4 |             0 |
| ...          | ...        |      ... |           ... |
+--------------+------------+----------+---------------+

Для тестирования теперь я создал временную таблицу tmp как результат GROUP BY из исходной таблицы статей новостей:

SELECT * FROM tmp LIMIT 6;
+--------------+------------+----------+-----+
| published_at | source     | category | cnt |
+--------------+------------+----------+-----+
| 2016-08-05   | 1826089206 |        3 |   1 |
| 2003-09-19   | 1826089206 |        4 |   1 |
| 2005-08-08   | 1826089206 |        3 |   1 |
| 2008-07-22   | 1826089206 |        4 |   1 |
| 2008-11-26   | 1826089206 |        8 |   1 |
| ...          | ...        |      ... | ... |
+--------------+------------+----------+-----+

Учитывая эти две таблицы, следующий запрос работает так, как ожидалось:

SELECT * FROM news_article_counts c, tmp t
WHERE c.published_at = t.published_at AND c.source = t.source AND c.category = t.category;

Но теперь мне нужно обновить article_count таблицы news_article_counts со значениями в таблице tmp где 3 параметра совпадают. Для этого я использую следующий запрос (я пробовал разные способы, но с теми же результатами):

UPDATE 
  news_article_counts c
INNER JOIN
  tmp t
ON
  c.published_at = t.published_at AND
  c.source = t.source AND
  c.category = t.category
SET
  c.article_count = t.cnt;

Выполнение этого запроса дает эту ошибку:

ERROR 1062 (23000): Duplicate entry '2018-04-07 14:46:17-1826089206-1' for key 'uniqueIndex'

uniqueIndex совлокальный индекс по published_at, source, category столовых news_article_counts. Но это не должно быть проблемой, поскольку я не могу - насколько я могу судить, обновить любое из этих 3 значений, только article_count.

Что меня больше смущает, так это то, что в ошибке упоминается временная метка, в которой я выполнил запрос (здесь: 2018-04-07 14:46:17). У меня нет абсолютно никакой идеи, где это вступает в игру. В самом деле, некоторые строки в news_article_counts теперь 2018-04-07 14:46:17 в качестве значения для published_at. В то время как это объясняет ошибку, я не могу понять, почему published_at переопределен с текущим временем. В этом столбце нет ON UPDATE CURRENT_TIMESTAMP; увидеть:

CREATE TABLE IF NOT EXISTS 'test'.'news_article_counts' (
  'published_at' TIMESTAMP NOT NULL,
  'source' INT UNSIGNED NOT NULL,
  'category' INT UNSIGNED NOT NULL,
  'article_count' INT UNSIGNED NOT NULL DEFAULT 0,
  UNIQUE INDEX 'uniqueIndex' ('published_at' ASC, 'source' ASC, 'category'  ASC))
ENGINE = MyISAM
DEFAULT CHARACTER SET = utf8mb4;

Что мне здесь не хватает?

ОБНОВЛЕНИЕ 1: Я фактически проверил определение таблицы news_article_counts в базе данных. И действительно, есть следующее:

mysql> SHOW COLUMNS FROM news_article_counts;
+---------------+------------------+------+-----+-------------------+-----------------------------+
| Field         | Type             | Null | Key | Default           | Extra                       |
+---------------+------------------+------+-----+-------------------+-----------------------------+
| published_at  | timestamp        | NO   |     | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
| source        | int(10) unsigned | NO   |     | NULL              |                             |
| category      | int(10) unsigned | NO   |     | NULL              |                             |
| article_count | int(10) unsigned | NO   |     | 0                 |                             |
+---------------+------------------+------+-----+-------------------+-----------------------------+

Но почему on update CURRENT_TIMESTAMP установлен on update CURRENT_TIMESTAMP. Я дважды и трижды проверил свой оператор CREATE TABLE. Я удалил общий индекс, я добавил искусственный первичный ключ (auto_increment). Ничего не помогает. Я даже попытался явно удалить эти атрибуты из published_at с помощью:

ALTER TABLE 'news_article_counts' CHANGE 'published_at' 'published_at' TIMESTAMP NOT NULL;

Ничто не работает для меня.

  • 0
    dev.mysql.com/doc/refman/5.7/en/timestamp-initialization.html
  • 0
    @ ZamronyP.Juhara Но он не использует эту опцию.
Показать ещё 8 комментариев
Теги:
sql-update
mysql-error-1062

1 ответ

1
Лучший ответ

Похоже, что вы отключили системную переменную explicit_defaults_for_timestamp. Одним из последствий этого является:

Первый столбец TIMESTAMP в таблице, если явно не объявлен с атрибутом NULL или явным атрибутом DEFAULT или ON UPDATE, автоматически объявляется с атрибутами DEFAULT CURRENT_TIMESTAMP и ON UPDATE CURRENT_TIMESTAMP.

Вы можете попробовать включить эту системную переменную, но это может повлиять на другие приложения. Я думаю, что это вступает в силу только тогда, когда вы создаете таблицу, поэтому она не должна влиять на существующие таблицы.

Если вы этого не сделаете, чтобы сделать изменения на уровне системы, как это, вы могли бы добавить явное DEFAULT атрибут в published_at столбце этой таблицы, то он не будет автоматически добавлять ON UPDATE.

  • 0
    место на! Я только что проверил это и решил все. Очень ценится!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню