我有一组不同类型的用户,每种类型都有一组存储用户设置的字段。我的想法是将user_id
和user_type
存储在一个具有常见字段集的表中,并将其他设置移动到单独的表中。但问题是如何将用户从公用表链接到他的详细信息在单独的表中。我看到一个解决方案是将与某个用户类型相关联的表名存储在另一个表中。但这是最好的解决方案吗?
CREATE TABLE IF NOT EXISTS `mydb`.`user` (
`user_id` INT NOT NULL,
`user_name` INT NOT NULL,
`user_type` INT NULL,
PRIMARY KEY (`user_id`, `user_name`),
UNIQUE INDEX `adv_id_UNIQUE` (`user_id` ASC),
INDEX `adv_type_idx` (`user_type` ASC),
CONSTRAINT `adv_type`
FOREIGN KEY (`user_type`)
REFERENCES `mydb`.`user_type` (`type_id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
CREATE TABLE IF NOT EXISTS `mydb`.`user_type` (
`type_id` INT NOT NULL,
`type_table` VARCHAR(45) NULL,
UNIQUE INDEX `type_id_UNIQUE` (`type_id` ASC),
PRIMARY KEY (`type_id`))
//TABLES WITH SEPARATE SET OF FIELDS
CREATE TABLE IF NOT EXISTS `mydb`.`user_details_admin` (
`user_id` INT NOT NULL,
`user_admin` VARCHAR(45) NULL,
PRIMARY KEY (`user_id`))
CREATE TABLE IF NOT EXISTS `mydb`.`user_details_moderator` (
`user_id` INT NOT NULL,
`user_moderator` VARCHAR(45) NULL,
PRIMARY KEY (`user_id`))
答案 0 :(得分:0)
这似乎是您希望在数据库中建模继承的情况。
不是将user_details_表名存储在user_types表中,而是类似于以下内容可能会为您提供更好的服务:
CREATE TABLE IF NOT EXISTS 'mydb'.'user' (
'user_id' INT NOT NULL,
'type_id' INT NOT NULL,
'commonfield1' datatype (NOT) NULL,
'commonfield2' datatype (NOT) NULL,
'commonfield...' datatype (NOT) NULL,
PRIMARY KEY ('user_id', (other field as needed)),
UNIQUE INDEX 'adv_id_UNIQUE' ('user_id' ASC),
INDEX 'adv_type_idx' ('type_id' ASC),
CONSTRAINT 'adv_type'
FOREIGN KEY ('type_id')
REFERENCES 'mydb'.'user_type' ('type_id')
ON DELETE NO ACTION
ON UPDATE NO ACTION)
CREATE TABLE IF NOT EXISTS 'mydb'.'user_type' (
'type_id' INT NOT NULL,
'type_name' VARCHAR(45) NOT NULL,
UNIQUE INDEX 'type_id_UNIQUE' ('type_id' ASC),
UNIQUE INDEX 'type_name_UNIQUE' ('type_name' ASC),
PRIMARY KEY ('type_id'))
//TABLES WITH SEPARATE SET OF FIELDS
CREATE TABLE IF NOT EXISTS 'mydb'.'user_details_admin' (
'user_id' INT NOT NULL,
'type_id' INT NOT NULL,
'adminfield1' datatype (NOT) NULL,
'adminfield...' datatype (NOT) NULL,
PRIMARY KEY ('user_id'))
CONSTRAINT user_type_FK
FOREIGN KEY ('user_id', 'type_id')
REFERENCES 'mydb'.'user' ('user_id', 'type_id')
ON DELETE NO ACTION
ON UPDATE NO ACTION)
CREATE TABLE IF NOT EXISTS 'mydb'.'user_details_moderator' (
'user_id' INT NOT NULL,
'type_id' INT NOT NULL,
'moderatorfield1' datatype (NOT) NULL,
'moderatorfield...' datatype (NOT) NULL,
PRIMARY KEY ('user_id'))
CONSTRAINT user_type_FK
FOREIGN KEY ('user_id', 'type_id')
REFERENCES 'mydb'.'user' ('user_id', 'type_id')
ON DELETE NO ACTION
ON UPDATE NO ACTION)
此设计假设用户可能只有一种类型。例如,您需要确保moderator
仅使用触发器或视图添加到user_details_moderator
表,和/或在应用程序代码中处理它。 MySQL没有对表实现检查约束。无论如何,您可能希望创建视图,以避免每次要查询特定子类型时在JOIN
表和子类型表之间编写user
。
注意:INDEX
表格中type_id
上的user
可能没用或没必要。
这不是建模数据的唯一方法。如果您在表格中有很少不同的字段和/或愿意在表格中显示NULL
字段,则可以将所有字段添加到user
表中。除了先验 NULL
字段问题之外,这些方法之间的主要区别在于添加了具有新的不同字段的新user_type
。在我提供的示例中,您需要添加一个新表。在单表设计中,您需要向user
表添加新的可空字段。哪个更容易维护取决于你,但我个人更喜欢每个类型的表设计,因为在我的使用中添加一个表是相对微不足道的,我不喜欢故意添加我知道将包含NULL
'值的字段'没有严重的优化优势(在我的情况下不存在,但可能在你的情况下)。
另请参阅How do you effectively model inheritance in a database?和/或在database标记下搜索“继承”以获取更多信息。
答案 1 :(得分:0)
我认为使用user_id,parameter_key,parameter_value列创建user_type_parameters可能是一个有趣的解决方案,因为它会为您提供更大的灵活性。
parameter_key列将是某个参数的名称,如user_details_admin表中的一列,而在parameter_value列中,您将输入其对应的值。
当然,在应用程序方面,您必须知道每种用户类型的期望值。
请随意询问您对我的解释是否有任何疑问。