MySQL不允许一张表有多个主键,需检查建表语句中PRIMARY KEY出现次数,确保仅保留一个;复合主键须用PRIMARY KEY(col1,col2)统一声明,多字段唯一应改用UNIQUE约束。

直接删掉重复的 PRIMARY KEY 定义,只保留一个 —— MySQL 不允许一张表有多个主键,语法上就过不去。
检查建表语句里写了几个 PRIMARY KEY
这是最常见也最容易忽略的源头。比如你写了:
CREATE TABLE bookorder ( m_id CHAR(6) PRIMARY KEY, b_id CHAR(7) PRIMARY KEY );
MySQL 解析时会逐字段读取约束,遇到第一个 PRIMARY KEY 就记下,再遇到第二个就直接报 [Err] 1068 - Multiple primary key defined。它不等你写完括号,解析到第二个就终止。
- 复合主键必须写在表定义末尾,用
PRIMARY KEY(col1, col2)形式统一声明 - 不能对两个字段分别加
PRIMARY KEY,哪怕它们逻辑上都“唯一”也不行 - 如果想让多个字段都唯一,改用
UNIQUE约束,例如m_id UNIQUE, b_id UNIQUE
用 SHOW CREATE TABLE 查当前实际结构
DDL 语句没写错,但表已经存在且带主键,你又执行了另一条加主键的 ALTER TABLE ... ADD PRIMARY KEY,也会触发该错误。这时候不是语法问题,而是运行时冲突。
- 先运行
SHOW CREATE TABLE your_table;,看输出里是否已有PRIMARY KEY行 - 或者查数据字典:
SHOW KEYS FROM your_table WHERE Key_name = 'PRIMARY'; - 确认存在后,必须先
ALTER TABLE your_table DROP PRIMARY KEY;,再执行新加逻辑 - 注意:如果原主键含
AUTO_INCREMENT,得先MODIFY字段去掉自增,否则DROP PRIMARY KEY会失败
工具导出/同步时自动补主键导致重复
DbVisualizer、DBeaver、Navicat 或 otter 同步任务,在“重建表”或“迁移结构”时可能默认把某列当主键加回去,而目标表已有主键,就会在生成的 SQL 中出现两个 PRIMARY KEY。
- 不要直接运行工具生成的完整 DDL,先人工检查
CREATE TABLE或ALTER TABLE语句 - 重点盯
PRIMARY KEY出现次数和位置,尤其注意括号外的独立声明 - 如果是同步场景(如 otter 报错日志里出现
Multiple primary key defined),优先查目标库表是否已存在主键,而不是改源端 - 临时解决可加
IF NOT EXISTS?不行 —— MySQL 的ADD PRIMARY KEY不支持这个子句,必须显式判断并处理
真正容易被绕开的点是:你以为自己只定义了一次主键,但可能是建表语句 + 后续 ALTER + 工具自动补全三者叠加;只要最终 SQL 文本里 PRIMARY KEY 字符串出现超过一次,MySQL 就会拒绝执行。











