我有一个MySQL数据库,存储新闻文章,包括出版日期(仅日信息),来源和类别。基于这些我想生成一个表格,其中包含文章计数w.r.t.这3个参数。
由于这三个参数的某些组合可能没有文章,因此简单的GROUP BY不会。因此,我首先生成一个表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
中与3个参数匹配的值更新表news_article_counts
的{{1}}。为此,我使用以下查询(我尝试了不同的方法,但结果相同):
tmp
执行此查询会产生此错误:
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
的{{1}},published_at
,source
的联合索引。但这应该不是问题,因为我没有 - 据我所知 - 更新这3个值中的任何一个,只有category
。
最让我困惑的是,在错误中它提到了我执行查询的时间戳(这里:news_article_counts
)。我不知道这会发挥作用。实际上,article_count
中的某些行现在具有2018-04-07 14:46:17
作为news_article_counts
的值。虽然这解释了错误,但我看不出为什么2018-04-07 14:46:17
会被当前时间戳覆盖。此列中没有published_at
;见:
published_at
我在这里缺少什么?
UPDATE 1 :我实际检查了数据库中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;
但为什么设置news_article_counts
。我对我的CREATE TABLE语句进行了双重和三重检查。我删除了联合索引,我添加了一个人工主键(auto_increment)。什么都没有帮助。我甚至尝试使用以下内容从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
似乎没有什么对我有用。
答案 0 :(得分:1)
看起来您已禁用explicit_defaults_for_timestamp
系统变量。其中一个影响是:
如果未使用
TIMESTAMP
属性或显式NULL
或DEFAULT
属性显式声明,表中的第一个ON UPDATE
列会自动声明为{{ 1}}和DEFAULT CURRENT_TIMESTAMP
属性。
您可以尝试启用此系统变量,但这可能会影响其他应用程序。我认为它只会在您实际创建表格时生效,因此它不应影响任何现有表格。
如果您没有像这样进行系统级更改,可以在此表的ON UPDATE CURRENT_TIMESTAMP
列中添加明确的DEFAULT
属性,然后它就会赢了自动添加published_at
。