我当前正在尝试添加关联表,但其中一个外键因以下 InnoDB 状态而失败:
在引用的表中找不到索引 引用的列显示为第一列或列类型 表和引用表中的约束不匹配。 请注意,ENUM 和 SET 的内部存储类型发生了变化 使用 >= InnoDB-4.1.12 创建的表,以及旧表中的此类列 新表中的此类列无法引用。
被引用的表确实有主键。它位于相同的字符集/排序规则中。它使用 InnoDB 并且主键与新表中的 FK 具有相同的类型。
它有一个名为 PRIMARY 的索引,其中 pk 列已选中且为 #1。
这是所引用的表格
CREATE TABLE `oauthtokens` (
`useridentifier` varchar(100) CHARACTER SET utf8 NOT NULL,
`guid` varchar(36) CHARACTER SET utf8 DEFAULT NULL,
`accesstoken` varchar(100) CHARACTER SET utf8 NOT NULL,
`refreshtoken` varchar(100) CHARACTER SET utf8 NOT NULL,
`expirytime` varchar(45) CHARACTER SET utf8 NOT NULL,
`is_master_user` tinyint(1) DEFAULT '0',
PRIMARY KEY (`useridentifier`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
这是我正在尝试创建的新表
CREATE TABLE `UserRoles` (
`UserId` varchar(100) NOT NULL,
`RoleId` int NOT NULL,
PRIMARY KEY (`UserId`, `RoleId`),
CONSTRAINT `FK_UserRoles_Roles_RoleId` FOREIGN KEY (`RoleId`) REFERENCES `Roles` (`Id`) ON DELETE CASCADE,
CONSTRAINT `FK_UserRoles_oauthtokens_UserId` FOREIGN KEY (`UserId`) REFERENCES `oauthtokens` (`useridentifier`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
FK_UserRoles_Roles_RoleId 有效,但 FK_UserRoles_oauthtokens_UserId 无效。
我在8.0.17上测试了这个并得到了错误:
错误 3780 (HY000):在外键约束“FK_UserRoles_oauthtokens_UserId”中引用列“UserId”和引用列“useridentifier”不兼容。
UserRoles.UserId
使用表的默认字符集 utf8mb4,但您试图使其引用使用字符集 utf8 的列 oauthtokens.useridentifier
。
外键列及其引用的列必须使用相同的字符集和相同的排序规则。
我让它以这种方式工作:
ALTER TABLE oauthtokens CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
然后添加外键就可以了。
您可能想在这里阅读更完整的外键要求清单:https://stackoverflow.com/a/4673775/20860
我还在我的书SQL反模式卷1:避免数据库编程的陷阱中写了一章解释可能的外键错误。