3 테이블 간의 순환 종속성 (순환 참조)을 피하는 방법은 무엇입니까?


10

나는 3 개의 테이블이 있습니다 :

  • 사람들
  • 게시하다
  • 좋아요

ER 모델을 설계 할 때 순환 종속성이 있습니다.

         1 : N
사람들 -------- <Post

         1 : N
게시물 ---------- <좋아요

         1 : N
사람들 -------- <좋아요

논리는 다음과 같습니다.

  • 1 명이 많은 게시물을 가질 수 있습니다.

  • 1 개의 게시물에는 많은 좋아요가 있습니다.

  • 1 명이 많은 게시물을 좋아할 수 있습니다 (작성된 사람은 자신의 게시물을 좋아할 수 없음).

이런 종류의 주기적 디자인을 어떻게 제거 할 수 있습니까? 아니면 내 DB 디자인이 잘못 되었습니까?

답변:


10

비즈니스 규칙

제시 한 비즈니스 규칙에 대해 다음과 같이 다시 말씀 드리겠습니다.

  • A는 zero-one-or-many를Person 생성 합니다 Posts .
  • A Postzero-one-or-many를 Likes 받습니다.
  • A Person0에서 1까지 또는 다수 Likes 이며, 각각은 하나의 특정에 관련됩니다 Post.

논리 모델

그런 다음 이러한 어설 션 세트 에서 그림 1에 표시된 두 가지 논리 레벨 IDEF1X [1] 데이터 모델을 도출했습니다 .

그림 1-사람 및 게시물 데이터 모델

옵션 A

사용자가 옵션 A 모델에서 볼 수있는 바와 같이, PersonId 이 이동할 때 [2] 에서 Person으로 Post하지만,이 수신 FOREIGN KEY (FK)로서 역할 이름 [3] 중을 AuthorId함께,이 속성이 차지하는 PostNumber기본 키 (PK) 상기의 Post개체 유형.

나는이 가정 Like에만 특정과 관련하여 존재할 수 Post내가 설정 한, 그래서 Like: 그 세 가지 속성을 포함 PK를 PostAuthorId, PostNumber하고 LikerId. PostAuthorId와 PK 의 조합은 PK PostNumber를 올바르게 참조하는 FK입니다 Post. LikerId이는로 적절한 연관성을 설정하는 FK이다 Person.PersonId.

이 구조를 사용하면 결정된 사람 Like이 동일한 Post인스턴스에 단일 항목 만 표시 할 수 있습니다 .

게시물 작성자가 자신의 게시물을 좋아하지 못하게하는 방법

당신이 있기 때문에 하지 않는 사람이 자신을 좋아 할 수있는 가능성을 허용 할 구현 단계에서, 당신의 가치 비교하는 방법을 확립해야한다 일단 / 그녀는 게시물을 작성 Like.PostAuthorId의 값으로 Like.LikerId모든 INSERT 시도에있다. 상기 값이 일치하면 (a) 삽입을 거부하고, 일치하지 않으면 (b) 프로세스를 계속 진행합니다.

데이터베이스에서이 작업을 수행하기 위해 다음을 사용할 수 있습니다.

  1. CHECK 제약 물론 있지만,이 방법 제외 MySQL은, 당신이 볼 수 있듯이 그것은 지금까지이 플랫폼에서 구현되지 않았기 때문에 여기여기 .

  2. ACID 트랜잭션 내부의 코드 라인 .

  3. TRIGGER 내의 코드 행으로 , 규칙 위반 시도를 나타내는 사용자 정의 메시지를 리턴 할 수 있습니다.

옵션 B

작성자가 비즈니스 도메인의 게시물을 기본적으로 식별하는 속성이 아닌 경우 옵션 B에 표시된 것과 유사한 구조를 사용할 수 있습니다.

이 방법은 또한 같은 사람이 한 번만 게시물을 좋아할 수 있도록합니다.


노트

1. 정보 모델링 통합 정의 ( IDEF1X )는 1993 년 12 월 미국 표준 기술 연구소 ( NIST ) 에서 표준 으로 정의한 권장 데이터 모델링 기술 입니다 .

2. IDEF1X는 키 마이그레이션 을 "부모 또는 일반 엔터티의 기본 키를 자식 또는 범주 엔터티에 외래 키로 배치하는 모델링 프로세스"로 정의합니다 .

3. 역할 이름 은 해당 엔티티 유형의 컨텍스트에서 해당 속성의 의미를 표현하기 위해 외래 키 속성에 지정된 표시입니다. EF Codd 박사 는 1970 년부터 “대규모 공유 데이터 뱅크를위한 데이터의 관계형 모델” 이라는 제목의 논문에서 역할 명명을 권장 합니다. 그와 관련하여 IDEF1X ( 관계 유지 관행에 대한 충실도 유지) 도이 절차를 옹호합니다.


6

나는 여기에 주기적 인 것이 보이지 않습니다. 이 엔티티들 사이 에는 사람게시물 그리고 두 개의 독립적 인 관계가 있습니다. 이러한 관계 중 하나의 구현으로 좋아요 를 볼 수 있습니다.

  • 사람은 많은 게시물을 쓸 수 있으며 게시물은 한 사람이 작성합니다. 1:n
  • 사람은 많은 게시물을 좋아할 수 있고 많은 사람들이 게시물을 좋아할 수 있습니다 n:m
    . n : m 관계는 다른 관계로 구현 될 수 있습니다 likes.

기본 구현

기본 구현은 PostgreSQL 에서 다음과 같이 보일 수 있습니다 .

CREATE TABLE person (
  person_id serial PRIMARY KEY
, person    text NOT NULL
);

CREATE TABLE post (
  post_id   serial PRIMARY KEY
, author_id int NOT NULL  -- cannot be anonymous
     REFERENCES person ON UPDATE CASCADE ON DELETE CASCADE  -- 1:n relationship
, post      text NOT NULL
);

CREATE TABLE likes (  -- n:m relationship
  person_id int REFERENCES person ON UPDATE CASCADE ON DELETE CASCADE
, post_id   int REFERENCES post ON UPDATE CASCADE ON DELETE CASCADE
, PRIMARY KEY (post_id, person_id)
);

특히 게시물 에는 작성자 ( ) 가 있어야NOT NULL 하지만 좋아요의 존재는 선택 사항입니다. 기존의 추천을하지만, post하고 person 있어야 모두 적용 (참조 할 것을 PRIMARY KEY모두 열을 만드는 NOT NULL자동 (당신이 그렇게 익명 좋아도 불가능) 중복, 명시 적으로 이러한 제약을 추가 할 수 있습니다.

n : m 구현에 대한 세부 사항 :

자기 같은 것을 방지

당신은 또한 썼습니다 :

(만든 사람은 자신의 게시물을 좋아할 수 없습니다).

위의 구현에서는 아직 시행되지 않았습니다. 트리거를 사용할 수 있습니다 .
또는 더 빠르고 안정적인 솔루션 중 하나 :

비용이 많이 드는 견고한

그것이 될 필요가있는 경우 견고한 , 당신은에서 FK를 확장 할 수 likespost인클루드하는 author_id중복을. 그런 다음 간단한 CHECK제약 조건으로 근친상간을 배제 할 수 있습니다 .

CREATE TABLE likes (
  person_id int REFERENCES person ON UPDATE CASCADE ON DELETE CASCADE
, post_id   int 
, author_id int NOT NULL
, CONSTRAINT likes_pkey PRIMARY KEY (post_id, person_id)
, CONSTRAINT likes_post_fkey FOREIGN KEY (author_id, post_id)
     REFERENCES post(author_id, post_id) ON UPDATE CASCADE ON DELETE CASCADE
, CONSTRAINT no_self_like CHECK (person_id <> author_id)
);

다음과 같은 경우에도 중복 제약 이 필요 합니다 .UNIQUEpost

ALTER TABLE post ADD CONSTRAINT post_for_fk_uni UNIQUE (author_id, post_id);

나는 유용한 인덱스author_id제공하기 위해 먼저 제공 했다.

더 관련 답변 :

CHECK구속 조건 이있는 더 싼

위의 "기본 구현"을 기반으로합니다.

CHECK제약 조건은 변경 불가능합니다. 검사를 위해 다른 테이블을 참조하는 것은 결코 변하지 않습니다. 우리는 여기서 개념을 조금 남용합니다. NOT VALID이를 제대로 반영하기 위해 제약 조건을 선언하는 것이 좋습니다 . 세부:

CHECK게시물 작성자가 절대 변하지 않는 속성처럼 보이기 때문에이 특별한 경우 에는 제약이 합리적으로 보입니다. 해당 필드의 업데이트를 확실하게하지 마십시오.

우리 는 함수를 위조 합니다 IMMUTABLE:

CREATE OR REPLACE FUNCTION f_author_id_of_post(_post_id int)
  RETURNS int AS
'SELECT p.author_id FROM public.post p WHERE p.post_id = $1'
LANGUAGE sql IMMUTABLE;

'public'을 실제 테이블 스키마로 바꾸십시오. 제약 조건
에서이 함수를 사용하십시오 CHECK.

ALTER TABLE likes ADD CONSTRAINT no_self_like_chk
   CHECK (f_author_id_of_post(post_id) <> person_id) NOT VALID;

4

비즈니스 규칙을 설명하는 방식으로 인해이를 파악하는 데 어려움이 있다고 생각합니다.

사람과 게시물은 "개체"입니다. 동사처럼.

실제로 두 가지 작업이 있습니다.

  1. 사람은 하나 이상의 게시물을 만들 수 있습니다
  2. 많은 사람들이 많은 게시물을 좋아할 수 있습니다. (마지막 두 문장의 편집)

게시물 다이어그램을 좋아하는 사람

"likes"테이블은 person_id 및 post_id를 기본 키로 사용합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.