programing

MySQL - 일대일 관계

bestcode 2022. 12. 27. 21:17
반응형

MySQL - 일대일 관계

MySQL 데이터베이스에서 "1 대 1" 관계를 구축하려고 합니다.예를 들어 Users 테이블과 Accounts 테이블이 있다고 가정합니다.사용자가 계정을 하나만 가질 수 있는지 확인합니다.또한 사용자당 하나의 계정만 존재할 수 있습니다.

이에 대한 두 가지 해결책을 찾았는데 무엇을 사용해야 할지 모르겠고 다른 방법이 있나요?

첫 번째 솔루션:

DROP DATABASE IF EXISTS test;
CREATE DATABASE test CHARSET = utf8 COLLATE = utf8_general_ci;
USE test;

CREATE TABLE users(
    id INT NOT NULL AUTO_INCREMENT,
    user_name VARCHAR(45) NOT NULL,
    PRIMARY KEY(id)
) ENGINE = InnoDB DEFAULT CHARSET = utf8;

CREATE TABLE accounts(
    id INT NOT NULL AUTO_INCREMENT,
    account_name VARCHAR(45) NOT NULL,
    user_id INT UNIQUE,
    PRIMARY KEY(id),
    FOREIGN KEY(user_id) REFERENCES users(id)
) ENGINE = InnoDB DEFAULT CHARSET = utf8;

이 예에서는 사용자의 프라이머리 키를 가리키는 계정의 외부 키를 정의합니다.그리고 외부 키를 고유하게 만들어서 계정에 동일한 사용자가 두 명 있을 수 없습니다.테이블을 결합하려면 다음 쿼리를 사용합니다.

SELECT * FROM users JOIN accounts ON users.id = accounts.user_id;

두 번째 솔루션:

DROP DATABASE IF EXISTS test;
CREATE DATABASE test CHARSET = utf8 COLLATE = utf8_general_ci;
USE test;

CREATE TABLE users(
    id INT NOT NULL AUTO_INCREMENT,
    user_name VARCHAR(45) NOT NULL,
    PRIMARY KEY(id)
) ENGINE = InnoDB DEFAULT CHARSET = utf8;

CREATE TABLE accounts(
    id INT NOT NULL AUTO_INCREMENT,
    account_name VARCHAR(45) NOT NULL,
    PRIMARY KEY(id),
    FOREIGN KEY(id) REFERENCES users(id)
) ENGINE = InnoDB DEFAULT CHARSET = utf8;

이 예에서는 다른 테이블의 프라이머리 키에서 프라이머리 키를 가리키는 외부 키를 만듭니다.기본 키는 기본적으로 고유하므로 이 관계는 1 대 1이 됩니다.테이블을 결합하려면 다음을 사용합니다.

SELECT * FROM users JOIN accounts ON users.id = accounts.id;

이제 질문:

  • MySQL에서 일대일 관계를 만드는 가장 좋은 방법은 무엇입니까?
  • 이 두 가지 외에 다른 해결 방법이 있습니까?

MySQL Workbench를 사용하고 있는데, EER 다이어그램에서 One To One 관계를 설계하고 MySQL Workbench가 SQL 코드를 생성하도록 하면 One to Many 관계가 됩니다.이것이 바로 혼란스러운 점입니다.s

이러한 솔루션 중 하나를 MySQL Workbench EER 다이어그램에 Import하면 관계가 One to Many :S로 인식됩니다.이것도 혼란스럽습니다.

그렇다면 MySQL DDL에서 일대일 관계를 정의하는 가장 좋은 방법은 무엇일까요? 이를 위해 어떤 옵션이 있습니까?

기본 키는 기본적으로 고유하므로 이 관계는 1 대 1이 됩니다.

아니요, 그러면 "1 대 0 또는 1" 관계가 됩니다.그게 정말 필요한 거야?

그렇다면 "두 번째 솔루션"이 더 좋습니다.

  • 그게 더 간단해
  • 스토리지 사용률 감소1(따라서 캐시가 "확장"됨)
  • 관리해야2 할 지표를 줄이고 데이터 조작에 도움이 됩니다.
  • 그리고 (InnoDB를 사용하고 있기 때문에) 데이터를 자연스럽게 클러스터하기 때문에 서로 가까운 사용자는 자신의 계정을 서로 가깝게 저장하게 되므로 캐시 로컬성 및 특정 범위 스캔에 도움이 될 수 있습니다.

그나저나, 넌 이 모든 걸어야 해accounts.id통상적인 정수(자동 변환이 아님)를 지정합니다.

'아니오'의 경우 아래를 참조하십시오.

MySQL에서 일대일 관계를 만드는 가장 좋은 방법은 무엇입니까?

"best"는 오버로드된 단어이지만 "standard" 솔루션은 다른 데이터베이스와 동일합니다. 즉, 두 엔티티(사용자의 경우 사용자와 계정)를 동일한 물리적 테이블에 배치합니다.

이 두 가지 외에 다른 해결 방법이 있습니까?

이론적으로는 두 PK 간에 순환 FK를 만들 수 있지만, 안타깝게도 MySQL에서는 지원되지 않는 치킨 앤 에그 문제를 해결하려면 지연 제약이 필요합니다.

이러한 솔루션 중 하나를 MySQL Workbench EER 다이어그램에 Import하면 One to Many:S 로 인식됩니다.이것도 혼란스럽습니다.

저는 그 특별한 모델링 툴에 대한 실제 경험은 별로 없지만, 그것은 "1 대 다"라는 점에서 "많이"라는 면을 독특하게 만들어 1로 제한했기 때문이라고 생각합니다."many"는 "1 또는 many"가 아니라 "0 또는 many"를 의미하므로 "caped" 버전은 "0 또는 1"을 의미합니다.


1 추가 분야의 스토리지 비용뿐만 아니라 보조 인덱스에 대해서도 마찬가지입니다.또한 테이블을 항상 클러스터링하는 InnoDB를 사용하므로 클러스터된 테이블에서는 힙 기반 테이블보다 보조 인덱스가 훨씬 더 비싸다는 점에 유의하십시오.

2 InnoDB에는 외부 키에 대한 인덱스가 필요합니다.

은 계정 키 두 . 즉, 계정 테이블에는 후보 키 두 가 있습니다.id ★★★★★★★★★★★★★★★★★」user_id.

따라서 저는 두 번째 접근법, 즉 외부 키를 주요 키로 사용하는 방법을 제안합니다.이것은, 다음과 같습니다.

  • 하나 적은 열 사용
  • 각 행을 일의로 식별할 수 있습니다.
  • 계정을 사용자와 일치시킬 수 있습니다.

다음 접근방식은 어떻습니까?

  1. 테이블 사용자 생성

    CREATE TABLE `user` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `name` varchar(45) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
  2. 한 을 만듭니다.user_id ★★★★★★★★★★★★★★★★★」account_id키및를 "/"로 합니다.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. 테이블 user2 계정 만들기

    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;
    

이 솔루션은 데이터베이스에서 설치 공간이 가장 크지만 몇 가지 이점이 있습니다.

  • FK_Key를 사용자 테이블 또는 계정 테이블에 넣는 것은 1대 다의 관련성을 기대할 수 있습니다(사용자는 많은 계정을 가지고 있습니다).
  • 은 ★★★★★★에 비해,user2account하기 위해 되며, 다대다에 고유 합니다.user_id 등에 대하여account_id일대일 관계 이외의 것을 만들지 않도록 합니다.

이 솔루션에서 알 수 있는 주요 장점은 회사 내 다른 코드 레이어 또는 부서로 작업을 분할할 수 있다는 것입니다.

  • 사용자 생성은 A부문이 담당합니다.계정 테이블에 대한 쓰기 권한이 없어도 가능합니다.
  • B부문은 계정을 만듭니다.이것은 사용자 테이블에 대한 쓰기 권한이 없어도 가능합니다.
  • 매핑 작성은 부문 C에서 담당합니다.사용자 또는 계정 테이블에 대한 쓰기 권한이 없어도 가능합니다.
  • 부문 C가 매핑을 작성하면 부문 C에 먼저 매핑 삭제를 요구하지 않으면 부문 A 또는 B에 의해 사용자도 계정도 삭제할 수 없습니다.

언급URL : https://stackoverflow.com/questions/13644979/mysql-one-to-one-relationship

반응형