【问题标题】:MySQL UNIQUE KEY and FOREIGN KEY same column not getting createdMySQL UNIQUE KEY 和 FOREIGN KEY 相同的列未创建
【发布时间】:2025-12-17 00:05:01
【问题描述】:

我有以下表格/CREATE sintaxis:

CREATE TABLE `users` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `parentId` int(10) unsigned DEFAULT NULL,
  `fullName` varchar(50) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
  `alias` varchar(35) COLLATE utf8_unicode_ci DEFAULT NULL,
  `username` varchar(50) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
  `password` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_username` (`username`),
  UNIQUE KEY `uk_parentId_fullName_alias` (`parentId`,`fullName`,`alias`),
  KEY `fk_users_parentId` (`parentId`),
  CONSTRAINT `fk_users_parentId` FOREIGN KEY (`parentId`) REFERENCES `users` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

CREATE TABLE `userSettings` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `userId` int(11) unsigned NOT NULL,
  `settingsArray` text NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_userId` (`userId`),
  KEY `fk_userSettings_userId` (`userId`),
  CONSTRAINT `fk_userSettings_userId` FOREIGN KEY (`userId`) REFERENCES `users` (`id`) ON DELETE CASCADE
) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=latin1

我试图创建一个包含用户数据的表和另一个包含用户设置的表,当我创建 userSettings 表时它没有创建外键,创建 sintaxis 有什么问题吗?是否与为同一列创建两个索引有关?

创建 userSettings 表后得到的结果如下:

CREATE TABLE `userSettings` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `userId` int(11) unsigned NOT NULL,
  `settingsArray` text NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_userId` (`userId`),
  KEY `fk_userSettings_userId` (`userId`)
) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;

【问题讨论】:

  • 什么是错误信息?
  • @MohammadAliTaqvazadeh 没有显示错误,它只是创建了上面的表格

标签: mysql foreign-keys unique-key


【解决方案1】:

如您所见,MyISAM 不支持外键。 usersuserSettings 都必须是 InnoDB。

[我]只是好奇在同一列中是否有一个 UNIQUE_KEY 和 FOREIGN_KEY 是一种好习惯

这意味着userSettings 表中的每个userId 最多可以有一行。我猜您每个 userId 只需要一行,因为您在 settingsArray TEXT 列中存储了一个以某种方式编码的设置“数组”。 This is not a good practice.

您应该将每个设置存储在自己的列中:

CREATE TABLE `userSettings` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `userId` int(11) unsigned NOT NULL,
  `isAdmin` bool NOT NULL,
  `timezone` varchar(10) NOT NULL,
  `theme` varchar(10) NOT NULL,
  ...other settings...
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_userId` (`userId`),
  KEY `fk_userSettings_userId` (`userId`)
) 

否则每个userId 存储多行,每行有一个设置名称和值。

CREATE TABLE `userSettings` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `userId` int(11) unsigned NOT NULL,
  `setting` varchar(20) NOT NULL,
  `value` varchar(255) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_userId` (`userId`,`setting`),
  KEY `fk_userSettings_userId` (`userId`)
) 

如果userId 已经不是 NULL 和 UNIQUE,那么为什么您需要一个 id 列作为主键也是令人费解的,而且这可能是您无论如何都将用来查找行的键。您也可以将userId 设为主键(或第二个示例中的userId, setting),并省略id 列。

【讨论】:

  • 谢谢,为什么这被认为是不好的做法?即使每个用户都有不同的设置,而且许多用户会有很多列清空,最好单独做?
  • 使用 TEXT 存储任何设置数组意味着您无法有效搜索具有给定设置的用户。您也不能使用数据类型、索引、约束。如果不将整个数组提取到您的应用程序中并重新格式化,您将无法更新设置。但是如果你一次存储一个设置(就像我上面展示的任何一种设计),你就有更多的结构和更多的优化。
【解决方案2】:

刚刚意识到对于表 users ENGINE 是 InnoDB 而对于 userSettings 表 ENGINE 是 MyISAM,改变它并且工作,我只是好奇在同一列中是否有一个 UNIQUE_KEY 和 FOREIGN_KEY 是一个好习惯

【讨论】:

    最近更新 更多