insert into table ... select ... where not exists 报错

为提高效率,提问时请提供以下信息,问题描述清晰可优先响应。

  • 【TiDB 版本】:3.0.7
  • 【问题描述】:

TiDB 下报错:

mysql> insert into topic_views (topic_id, ip_address, viewed_at, user_id) select 18, '203.208.*.*', '2019-12-31', 712 where not exists (select 1 from topic_views where user_id = 712 and topic_id = 62283);
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your TiDB version for the right syntax to use line 1 column 120 near "where not exists (select 1 from topic_views where user_id = 712 and topic_id = 62283)"

MySQL 执行成功:

mysql> insert into topic_views (topic_id, ip_address, viewed_at, user_id) select 18, '203.208.*.*', '2019-12-31', 7 where not exists (select 1 from topic_views where user_id = 7 and topic_id = 62283);
Query OK, 1 row affected (0.01 sec)
Records: 1  Duplicates: 0  Warnings: 0

表结构:

CREATE TABLE `topic_views` (
  `topic_id` int(11) NOT NULL,
  `viewed_at` date NOT NULL,
  `user_id` int(11) DEFAULT NULL,
  `ip_address` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  UNIQUE KEY `uniq_ip_or_user_id_topic_views` (`user_id`,`ip_address`,`topic_id`),
  KEY `index_topic_views_on_topic_id_and_viewed_at` (`topic_id`,`viewed_at`),
  KEY `index_topic_views_on_user_id_and_viewed_at` (`user_id`,`viewed_at`),
  KEY `index_topic_views_on_viewed_at_and_topic_id` (`viewed_at`,`topic_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

请问是什么原因

@ohooono1 尝了下这是一个 TiDB 和 mysql 的语法兼容性问题, 我们可以在后续版本中兼容, 见 issue
https://github.com/pingcap/tidb/issues/14297
(如果有兴趣也欢迎来一起 fix 我们可以提供开发支持)

对于当前版本 TiDB 建议可以先修改 sql 为

insert into topic_views (topic_id, ip_address, viewed_at, user_id) select 18, '203.208.*.*', '2019-12-31', 7 from dual where not exists (select 1 from topic_views where user_id = 7 and topic_id = 62283);

加一个 from dual 绕过

谢谢,加了 from dual 后解决了我的问题。

还有一个小问题:groupsrank 好像是 TiDB 的保留关键字,但是我在 https://pingcap.com/docs-cn/stable/reference/sql/language-structure/keywords-and-reserved-words/ 里面没有找到

这个 groups 和 rank 是 mysql 的 window function 特性新引入的关键字,而在 TiDB 当前版本也对 window function 做了支持。

https://pingcap.com/docs-cn/stable/reference/sql/functions-and-operators/window-functions/#窗口函数

比较特殊的是在 enable window function 时这两个会被当作关键字处理。。而因为很可能一些老应用已经用 groups 和 rank 所以如果在 window function 没有开启的时候会被当做非关键字处理避免影响老应用。

keywords-and-reserved-words 文档没有体现最近的这个更新我们需要更新下文档

cool,谢谢你的详细解答.

:+1::+1: