MySQL - One To One Relation?

笑着哭i 提交于 2019-11-29 19:57:39

Since Primary Keys are UNIQUE by default, this makes this relation One to One.

No, that makes the relation "one to zero or one". Is that what you actually need?

If yes, then then your "second solution" is better:

  • it's simpler,
  • takes less storage1 (and therefore makes cache "larger")
  • hes less indexes to maintain2, which benefits data manipulation,
  • and (since you are using InnoDB) naturally clusters the data, so users that are close together will have their accounts stored close together as well, which may benefit cache locality and certain kinds of range scans.

BTW, you'll need to make accounts.id an ordinary integer (not auto-increment) for this to work.

If no, see below...

What is the best way to create One to One relation in MySQL?

Well, "best" is an overloaded word, but the "standard" solution would be the same as in any other database: put both entities (user and account in your case) in the same physical table.

Are there any other solutions other than these two?

Theoretically, you could make circular FKs between the two PKs, but that would require deferred constraints to resolve the chicken-and-egg problem, which are unfortunately not supported under MySQL.

And if I import any of these solutions into MySQL Workbench EER diagram, it recognizes relations as One to Many :S Thats also confusing.

I don't have much practical experience with that particular modeling tool, but I'm guessing that's because it is "one to many" where "many" side was capped at 1 by making it unique. Please remember that "many" doesn't mean "1 or many", it means "0 or many", so the "capped" version really means "0 or 1".


1 Not just in the storage expense for the additional field, but for the secondary index as well. And since you are using InnoDB which always clusters tables, beware that secondary indexes are even more expensive in clustered tables than they are in heap-based tables.

2 InnoDB requires indexes on foreign keys.

Your first approach creates two candidate keys in the accounts table: id and user_id.

I therefore suggest the second approach i.e. using the foreign key as the primary key. This:

  • uses one less column
  • allows you to uniquely identify each row
  • allows you to match account with user

What about the following approach

  1. Create Table user

    CREATE TABLE `user` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `name` varchar(45) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
  2. Create Table account with a unique index on user_id and account_id with a foreign key relation to user/account and a primary key on user_id and account_id

    CREATE TABLE `account` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `name` varchar(45) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
  3. Create Table user2account

    CREATE TABLE `user2account` (
      `user_id` int(11) NOT NULL,
      `account_id` int(11) NOT NULL,
      PRIMARY KEY (`user_id`,`account_id`),
      UNIQUE KEY `FK_account_idx` (`account_id`),
      UNIQUE KEY `FK_user_idx` (`user_id`),
      CONSTRAINT `FK_account` FOREIGN KEY (`account_id`) REFERENCES         `account` (`id`),
      CONSTRAINT `FK_user` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    

While this solution has the largest footprint in the database, there are some advantages.

  • Putting the FK_Key in either the user table or the account table is something that I expect to be a one to many releation (user has many accounts ...)
  • While this user2account approach is mainly used to define a many to many relationship, adding a UNIQUE constraint on user_id and on account_id will prevent creating something else than a one to one relation.

The main advantage I see in this solution is that you can divide the work in different code layers or departements in a company

  • Department A is responsible for creating users, this is possible even without write permission to accounts table
  • Departement B is responsible for creating accounts, this is possible even without write permission to user table
  • Departement C is responsible for creating the mapping, this is possible even without write permission to user or account table
  • Once Departement C has created a mapping neither the user nor the account can be deleted by departement A or B without asking departement C to delete the mapping first.
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!