“두 테이블 떨어져”제약 조건 시행


10

SQL에서 전기 회로도를 모델링하는 데 문제가 발생했습니다. 내가 캡처하고 싶은 구조는

  part ←────────── pin
                   
part_inst ←───── pin_inst

여기서 "inst"는 "instance"의 줄임말입니다.

예를 들어, s 1OUT, 1IN-, 1IN +, GND, 2IN +, 2IN-, 2OUT 및 V CCpart있는 LM358 연산 증폭기 가있을 수 있습니다 . 그런 다음이 부품을 회로도에 배치하여 a 및 8을 만들 수 있습니다.pinpart_instpin_inst

데이터 필드를 무시하고 스키마에서 처음 시도한 것은

create table parts (
    part_id bigserial primary key
);
create table pins (
    pin_id bigserial primary key,
    part_id bigint not null references parts
);
create table part_insts (
    part_inst_id bigserial primary key,
    part_id bigint not null references parts
);
create table pin_insts (
    pin_inst_id bigserial primary key,
    part_inst_id bigint not null references part_insts,
    pin_id bigint not null references pins
);

이 스키마의 주된 문제는이 때문이다 pin_inst에 연결 될 수 part_instpart_id=1있지만이 pin있다 part_id=2.

응용 프로그램 수준이 아닌 데이터베이스 수준 에서이 문제를 피하고 싶습니다. 그래서 기본 키를 수정하여 적용했습니다. 변경된 줄을로 표시했습니다 --.

create table parts (
    part_id bigserial primary key
);
create table pins (
    pin_id bigserial,                                          --
    part_id bigint not null references parts,
    primary key (pin_id, part_id)                              --
);
create table part_insts (
    part_inst_id bigserial,                                    --
    part_id bigint not null references parts,
    primary key (part_inst_id, part_id)                        --
);
create table pin_insts (
    pin_inst_id bigserial primary key,
    part_inst_id bigint not null,                              --
    pin_id bigint not null,                                    --
    part_id bigint not null references parts,                  --
    foreign key (part_inst_id, part_id) references part_insts, --
    foreign key (pin_id, part_id) references pins              --
);

이 방법 나의 불만은 기본 키를 오염이다 : 나는 참조 어디서나 part_inst, 내가 모두 추적 계속해야 part_inst_id하고,을 part_id. pin_inst.part_inst.part_id = pin_inst.pin.part_id지나치게 자세 하지 않고 제약 조건 을 적용 할 수있는 다른 방법이 있습니까?


pin_inst_id중복 성인 것도 제거 할 수 있습니다. (part_inst_id, part_id, pin_id)기본 키로 사용할 수 있습니다 .
ypercubeᵀᴹ

두 가지 : (a) 1OUT, 1IN-, 1IN +, GND, 2IN +, 2IN-, 2OUT 및 VCC가 11 핀 인스턴스를 생성하지 않습니까? (b) 나는 당신의 초기 스키마를 얻지 못했습니다. 둘 이상의 부품에 핀을 사용할 수 없습니까? 1-N이 아닌 핀과 부품간에 NN 관계가 필요합니다.
Marcus Junius Brutus

@ user34332 : (a) 숫자는 이름의 일부입니다. 예를 들어 "2OUT"은 단일 핀입니다. 여기의 개략도 나는 문제에 대해서 이야기하고는. (b) 동의하지 않습니다. 확실히 두 부분에는 VCC (양의 공급 전압, "공통 컬렉터에서 전압") 핀이있을 수 있지만 논리적으로 다른 핀입니다. 예를 들어, VCC 핀 하나는 일반적으로 500µA와 다른 하나는 250µA를 소비 할 수 있습니다.
Snowball 2019

@Snowball 샘플 데이터로 SQL-Fiddle 을 추가 한 경우 다른 사람이 스키마를 이해하는 데 도움이됩니다 .
ypercubeᵀᴹ

답변:


13

최소 솔루션

근본적인 해결책 중 하나는 pin_inst완전히 제거하는 것입니다 .

  part ←────────── pin
                   
part_inst ←───── pin_inst

귀하의 질문에 실제로 중복 테이블이 필요하다는 것을 제안하는 것은 없습니다. 들어 pinA와 관련된의 part_inst상기,보기 pin관련의의 part.

그러면 코드가 간단 해집니다.

create table part (    -- using singular terms for table names
    part_id bigserial primary key
);
create table pin (
    pin_id bigserial primary key,
    part_id bigint not null references part
);
create table part_inst (
    part_inst_id bigserial primary key,
    part_id bigint not null references part
);

그러나 귀하의 의견은 우리가 그걸로 도망 가지 않을 것이라고 분명히했습니다 ...

pin_inst필요한 경우 대안

포함 part_id당신이했던 것처럼하는 것은 외래 키 제약 간단한 솔루션입니다. 외래 키 제약 조건을 가진 테이블“두 테이블 떨어져”를 참조 할 수 없습니다 .

그러나 최소한 기본 키를 "오염"시키지 않고는 할 수 있습니다. UNIQUE구속 조건을 추가하십시오 .

create table part (
    part_id bigserial primary key
);
create table pin (
    pin_id bigserial primary key,
    part_id bigint not null references part,
    unique(part_id, pin_id)         -- note sequence of columns
);
create table part_inst (
    part_inst_id bigserial primary key,
    part_id bigint not null references part,
    unique(part_id, part_inst_id)
);
create table pin_inst (
    pin_inst_id bigserial primary key,
    part_inst_id bigint not null,
    pin_id bigint not null,
    part_id bigint not,
    foreign key (part_id, pin_id) references pin,
    foreign key (part_id, part_inst_id) references part_inst
);

나는 part_id독특한 제약 조건을 먼저 생각했습니다. 이는 참조 무결성과 관련이 없지만 성능에 중요합니다. 기본 키는 이미 pk 열에 대한 색인을 구현합니다. 고유 제한 조건을 구현하는 다중 컬럼 인덱스에서 다른 컬럼을 먼저 갖는 것이 좋습니다 . 이러한 관련 질문에 대한 세부 사항 :

SO 관련 질문 :

방아쇠를 가진 대안

더 유연하지만 조금 더 복잡하고 오류가 발생하기 쉽고 덜 엄격한 트리거 기능을 사용할 수 있습니다. 장점 : 당신은없이 할 수 part_inst.part_id있고 pin.part_id...


에 추가 열이 pin_insts있지만 가독성을 위해 열을 생략했습니다 ( "데이터 필드 무시, [...]"). 예를 들어, a pin_inst는 입력 또는 출력으로 표시 될 수 있습니다.
눈덩이

@ Snowball : 사실이되기 쉬웠을 것입니다. 귀하의 솔루션을 조금 확장했습니다.
Erwin Brandstetter 1

2
두 번째 제안은 내 상황에 잘 맞습니다. 외래 키가 기본 키 이외의 것을 참조 할 수 있다는 것을 알지 못했습니다.
눈덩이
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.