DigitalOcean拒绝导入表提示无主键,但表已通过ALTER定义主键
问题背景
导入SQL Dump时触发如下报错:
ERROR 3750 (HY000) at line 30: Unable to create or change a table without a primary key, when the system variable 'sql_require_primary_key' is set. Add a primary key to the table or unset this variable to avoid this message. Note that tables without a primary key can cause performance problems in row-based replication, so please consult your DBA before changing this setting.
报错原因是DigitalOcean数据库开启了sql_require_primary_key强制约束,要求CREATE TABLE时必须直接声明主键,但现有SQL是先创建无主键的表,再通过ALTER TABLE添加主键,导致建表阶段就被拦截。
可行解决方案
方案1:修改CREATE TABLE语句,直接在表定义中声明主键
将原有的建表语句与后续添加主键的ALTER语句合并,在CREATE TABLE阶段就定义主键和索引,同时保留自增配置。修改后的AspNetRoleClaims表语句如下:
CREATE TABLE `AspNetRoleClaims` ( `Id` int(11) NOT NULL AUTO_INCREMENT, `RoleId` varchar(255) NOT NULL, `ClaimType` longtext DEFAULT NULL, `ClaimValue` longtext DEFAULT NULL, PRIMARY KEY (`Id`), KEY `IX_AspNetRoleClaims_RoleId` (`RoleId`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
修改后可删除原SQL中对应的ALTER TABLE ... ADD PRIMARY KEY语句,保留外键约束的ALTER语句即可。这种方式完全符合数据库的主键强制要求,是最规范的解决方式。
方案2:临时关闭当前会话的主键强制约束
在SQL Dump的最开头添加一行会话级变量设置,临时关闭主键强制要求,该设置仅对当前导入会话有效,不会修改数据库全局配置:
SET sql_require_primary_key = OFF;
将这行代码放在SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";之前即可,这样建表阶段不会被拦截,后续的ALTER添加主键、外键的操作都能正常执行。此方案无需修改大量表结构语句,适合批量导入多个类似表的场景。
内容的提问来源于stack exchange,提问作者Matt Welander

