Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Normalizacja sprawia, że ​​sprzężenia między wieloma tabelami są trudne

Nie będę mówić o błędach ortograficznych. Ponieważ importujesz dane, błędy ortograficzne są lepiej obsługiwane w tabeli pomostowej.

Spójrzmy na tę nieco uproszczoną wersję.

create table stores
(
  store_name varchar(50) primary key,
  street_num varchar(10) not null,
  street_name varchar(50) not null,
  city varchar(50) not null,
  state_code char(2) not null,
  zip_code char(5) not null,
  iso_country_code char(2) not null,
  -- Depending on what kind of store you're talking about, you *could* have
  -- two of them at the same address. If so, drop this constraint.
  unique (street_num, street_name, city, state_code, zip_code, iso_country_code)
);  

insert into stores values 
('Dairy Queen #212',  '232', 'N 1st St SE',   'Castroville',  'CA', '95012', 'US'),
('Dairy Queen #213',  '177', 'Broadway Ave',  'Hartsdale',    'NY', '10530', 'US'),
('Dairy Queen #214', '7640', 'Vermillion St', 'Seneca Falls', 'NY', '13148', 'US'),
('Dairy Queen #215', '1014', 'Handy Rd',      'Olive Hill',   'KY', '41164', 'US'),
('Dairy Mart #101',   '145', 'N 1st St SE',   'Castroville',  'CA', '95012', 'US'),
('Dairy Mart #121',  '1042', 'Handy Rd',      'Olive Hill',   'KY', '41164', 'US');

Chociaż wiele osób mocno wierzy, że kod pocztowy określa miasto i stan w USA, tak nie jest. Kody pocztowe mają związek z tym, jak przewoźnicy jeżdżą swoimi trasami, a nie z geografią. Niektóre miasta przekraczają granice między państwami; trasy z pojedynczym kodem pocztowym mogą przekraczać linie stanu. Nawet Wikipedia to wie , chociaż ich przykłady mogą być nieaktualne. (Trasy dostaw stale się zmieniają.)

Mamy więc tabelę, która ma dwa klucze kandydujące,

  • {store_name} i
  • {numer_ulicy, nazwa_ulicy, miasto, kod_stanu, kod_zip, kod_kraju_izo}

Nie ma atrybutów niekluczowych. Myślę, że ten stół jest w 5NF. Co o tym myślisz?

Gdybym chciał zwiększyć integralność danych dla nazw ulic, mógłbym zacząć od czegoś takiego.

create table street_names
(
  street_name varchar(50) not null,
  city varchar(50) not null,
  state_code char(2) not null,
  iso_country_code char(2) not null,
  primary key (street_name, city, state_code, iso_country_code)
);  

insert into street_names
select distinct street_name, city, state_code, iso_country_code
from stores;

alter table stores
add constraint streets_from_street_names
foreign key             (street_name, city, state_code, iso_country_code)
references street_names (street_name, city, state_code, iso_country_code);
-- I don't cascade updates or deletes, because in my experience
-- with addresses, that's almost never the right thing to do when a 
-- street name changes.

Możesz (i prawdopodobnie powinieneś) powtórzyć ten proces dla nazw miast, nazw stanów (kody stanów) i nazw krajów.

Niektóre problemy z Twoim podejściem

Najwyraźniej możesz wprowadzić numer identyfikacyjny ulicy w Stanach Zjednoczonych wraz z identyfikatorem kraju dla Chorwacji. („Pełna nazwa miasta, że ​​tak powiem, to rodzaj faktów, które prawdopodobnie chcesz przechowywać w celu zwiększenia integralności danych. Prawdopodobnie dotyczy to również „pełnej nazwy” ulicy.)

Używanie numerów identyfikacyjnych dla każdego bitu danych znacznie zwiększa liczbę wymaganych złączeń. Używanie numerów identyfikacyjnych nie ma nic wspólnego z normalizacją. Używanie numerów identyfikacyjnych bez odpowiadających im unikalnych ograniczeń w kluczach naturalnych — całkowicie powszechny błąd — pozwala na duplikowanie danych.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Szczegółowe spojrzenie na indeksowanie baz danych

  2. wielokrotna aktualizacja przy użyciu ajax z php

  3. Dodawanie sekund do daty i godziny w MySQL

  4. LOAD DATA LOCAL INFILE zabronione w... PHP

  5. Typ danych MySQL DECIMAL