Czy potrzebuję osobnej kolumny Id dla tej tabeli „mapowania”?

10

Mam tabelę Producersi tabelę Products, z których oba mają postać:

  • Id - int, klucz podstawowy
  • Name - nvarchar

Producent może przenosić wiele Produktów, więc zamierzałem stworzyć tabelę o nazwie, ProducerDetailsktóra miałaby:

  • ProducerId - int, klucz obcy do Producers.Id
  • ProductId - int, klucz obcy do Products.Id

Potem zacząłem zadawać sobie pytania, więc pomyślałem, że zapytam ekspertów. Czy lepszym rozwiązaniem byłoby zaprojektowanie dodatkowej Idkolumny (int, klucz główny) w mojej ProducerDetailstabeli? Czy to jest niepotrzebne?

Używam SQL-Server 2008 R2, jeśli w ogóle coś to robi.

EDYCJA - Relacje między tymi tabelami byłyby, moim zdaniem, wiele do wielu, przepraszam, że nie wyjaśniłem tego. Producent może przewozić wiele rodzajów produktów, a ten sam produkt może być wytwarzany przez wielu różnych producentów.

Przepraszam, jeśli to pytanie jest zbyt proste, integralność referencyjna / projektowanie bazy danych nie jest moją mocną stroną (chociaż staram się to poprawić).

Josh Darnell
źródło

Odpowiedzi:

6

Jeśli masz relację jeden-do-wielu między producentami a produktami (innymi słowy, produkt może należeć tylko do jednego producenta), wówczas sensowne byłoby po prostu umieszczenie odwołania do klucza obcego bezpośrednio w Productstabeli:

Jeden za dużo

create table Producer
(
    id int identity(1, 1) not null primary key clustered,
    Name varchar(100) not null
)
go

create table Product
(
    id int identity(1, 1) not null,
    Name varchar(100) not null,
    ProducerId int not null foreign key references Producer(id)
)
go

Ale jeśli istnieje szansa, że ​​będzie to relacja wielu do wielu, najlepszym rozwiązaniem będzie skorzystanie ze stołu dołączenia.

Wiele do wielu

create table Producer
(
    id int identity(1, 1) not null primary key clustered,
    Name varchar(100) not null
)
go

create table Product
(
    id int identity(1, 1) not null primary key clustered,
    Name varchar(100) not null
)
go

create table ProductProducer
(
    ProductId int not null foreign key references Product(id),
    ProducerId int not null foreign key references Producer(id)
)
go

-- adding the primary key also ensures uniqueness
alter table ProductProducer
add constraint PK_ProductProducer 
primary key (ProductId, ProducerId)
go

Jeśli zdecydujesz się na stolik Join, nie będziesz musiał mieć dodatkowego klucza, ponieważ kombinacja ProductId/ProducerIdbędzie ostatecznie unikalna. Możesz użyć ich jako klucza złożonego, więc nie potrzebujesz dodatkowego Idpola ProductProducer.

Thomas Stringer
źródło
1
Nie odpowiadasz jednak na prawdziwe pytanie - pyta, czy posiadanie idpola w jego tabeli relacji ma jakąkolwiek wartość ?
JNK
@JNK Zredagowałem swoje pytanie. Jeśli ProductId, ProducerIdjest to unikalna kombinacja, nie widzę potrzeby dodawania kolejnego sztucznego klucza do tabeli Join. Zgoda? I chyba chyba nie rozumiem pytania, OP nie musi nawet używać tabeli Join dla tego przypadku użycia.
Thomas Stringer
@ jadarnel27 Ok, dziękuję za wyjaśnienie. Przekreśliłem tę część mojej odpowiedzi (choć uważam, że rozsądnie jest mieć trochę miejsca na dalsze informacje).
Thomas Stringer
7

Nie, dodanie wartości dodatkowego klucza podstawowego do tej tabeli nie ma żadnej wartości. Wasze dołączenia będą się odnosić tylko ProducerIDi ProductIDdlatego jest to tylko ciężar własny. MOIM ZDANIEM.

Chociaż zgadzam się z @Shark, że tabela łączenia nawet nie wydaje się tutaj potrzebna, chyba że robisz wszystko, aby nie zmieniać schematu istniejących tabel w jakikolwiek sposób.

Nawiasem mówiąc, uważam również, że warto nazwać swój główny identyfikator w całości (np. Products.ProductIDZamiast Products.ID), aby identyfikator był konsekwentnie nazywany w całym schemacie.

Aaron Bertrand
źródło
@ jadarnel27: W przypadku wszystkich innych kolumn tak uważa się za złą praktykę. W przypadku kolumny PK wielu woli używać tego stylu ( ProductID). Zaletą jest to, że kiedy zobaczysz an SometableID, natychmiast wiesz, do której tabeli się odnosi. Innym jest to, że możesz użyć Product JOIN ProducerDetail USING(ProductID)składni zamiast dłuższejProduct JOIN ProducerDetail ON Product.ID = ProducerDetail.ProductID
ypercubeᵀᴹ
Niestety, myślę, że USING(ProductID)nie jest dostępny w SQL-Server, więc ten punkt nie ma zastosowania.
ypercubeᵀᴹ