2011-09-22 8 views
5

Oto prosty przykład:Jak określić domyślny adres wysyłki klientów w tabeli bazy danych?

Załóżmy, że mam tabelę klientów, która ma relację jeden-do-wielu z tabelą adresów (klient może mieć wiele adresów wysyłki, ale adres wysyłki może należeć tylko do jednego klienta).

Customer Table 
------------- 
customer_id (PK) 


Address Table 
------------- 
address_id (PK) 
customer_id (FK) 

Teraz chcę, aby każdy klient mógł określić domyślny adres wysyłki.

Mogę wymyślić 2 sposoby, ale obie mają wady.

Wariant 1

Dodaj kolumnę logiczną do tabeli Adres nazwie "is_default".

Plusy

  1. kwerendy wybierające są proste
  2. Prosta dla innych ludzi, aby zrozumieć, jeśli oni zobaczyć model DB

Wady

  1. Aplikacja jest fo rced, aby wymusić i utrzymać "tylko jeden wiersz może być domyślnym" ograniczeniem.
  2. Aktualizacja domyślnego pola jest uciążliwa, ponieważ wymaga od aplikacji sprawdzenia i zresetowania poprzedniej domyślnej opcji.

Opcja 2

Dodaj kolumnę do tabeli użytkownika o nazwie „address_id” i sprawiają, że klucz obcy (null pozwalają również na wszelki wypadek nie istnieje adres).

Plusy

  1. łatwe do aktualizacji adresu domyślnej jeśli użytkownik zdecyduje się ją zmienić.
  2. Baza danych utrzymuje "tylko jeden wiersz może być domyślnym" ograniczeniem.

Wady

  1. muszę dodać nową kolumnę do indeksowanej tabeli Klienci za każdym razem postanawiam dodać jakieś domyślnego metadanych.

  2. Wygląda hack

Moje pytanie brzmi, czy jest to standardowy sposób obsłużyć tego rodzaju scenariusza, że ​​jestem z widokiem? Oczywiście są inne opcje (może tworzenie domyślnej tabeli wartości EAV?), Ale wolałbym, aby było to tak proste, jak to tylko możliwe, ponieważ zmiana jest wprowadzana do istniejącej podstawy kodu, więc nie chcę niczego łamać.

Odpowiedz

1

(może tworząc EAV domyślne opcje tabeli?)

chciałbym to zrobić, szczególnie jeśli martwisz się o łamaniu istniejącego kodu.

Customer_Defaults 
------------------------------------ 
customer_id       PK, FK -> Customer 
default_shipping_address_id   FK -> Address 

Czy to nie jest uporządkowane? Przeciągając całość do oddzielnego stołu, pozostawiasz istniejące tabele w spokoju. Jeśli używasz jakiejś warstwy ORM, obiekt nad nową tabelą może być bezpośrednio zapytany, a następnie możesz przejść do obiektu Adres. Nie trzeba nawet wprowadzać nowego obiektu do istniejących obiektów klientów lub adresów.

+0

Myślałem o tym, ale wtedy musiałbym stworzyć nową tabelę „domyślne” na każdym stole, że wymaga to domyślna karta kredytowa stanowi –

+0

@BillH: Dlaczego? Nic nie stoi na przeszkodzie, aby dodać kolejną kolumnę, 'default_credit_card_id', która wskazuje na tabelę Credit_Card. Nazwa tabeli jest wystarczająco ogólna, aby uchwycić * wszystkie * wartości domyślne dla klienta. – Mac

0

Kiedy rosną nowe wymagania, pomyśl o nowych tabelach. Oto dwa różne sposoby podejścia do problemu. Pierwszy jest mniej rygorystyczny niż drugi. (Chciałbym użyć drugiego.) Przyjmę, że "Tabela adresów" nazywa się "customer_addresses".

create table default_shipping_addresses (
    customer_id integer primary key references customers (customer_id), 
    shipping_addr_id integer not null unique references addresses (addr_id) 
); 

create table default_shipping_addresses (
    customer_id integer primary key references customers (customer_id), 
    shipping_addr_id integer not null unique references addresses (addr_id), 

    -- Add a UNIQUE constraint on customer_addresses (customer_id, address_id). 
    -- Since address_id is the primary key, it's unique, so (customer_id, 
    -- address_id) will also be unique. But you need the UNIQUE constraint to 
    -- allow a foreign key to reliably reference it, even in MySQL. 
    foreign key (customer_id, shipping_addr_id) 
    references customer_addresses (customer_id, address_id) 
); 
+0

Nie mogę po prostu utworzyć złożonego klucza podstawowego między adresami customer_id i shipping_addr_id z 2 kluczami obcymi wskazującymi odpowiednie źródła? –

Powiązane problemy