sql >> Database teknologi >  >> RDS >> Mysql

Normalisering gør joinforbindelser på tværs af flere tabeller vanskelige

Jeg vil ikke tale om stavefejl. Da du importerer dataene, håndteres stavefejl bedre i en opstillingstabel.

Lad os se på denne lidt forenklede version.

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');

Selvom mange mennesker er overbevist om, at postnummer bestemmer by og stat i USA, er det ikke tilfældet. Postnummer har at gøre med, hvordan luftfartsselskaber kører deres ruter, ikke med geografi. Nogle byer skræver grænserne mellem stater; enkelt postnummer ruter kan krydse staten linjer. Selv Wikipedia ved dette , selvom deres eksempler måske er forældede. (Leveringsruter ændrer sig konstant.)

Så vi har en tabel, der har to kandidatnøgler,

  • {store_name} og
  • {gadenummer, gadenavn, by, delstatskode, postnummer, iso_landekode

Den har ingen ikke-nøgleattributter. Jeg tror, ​​denne tabel er i 5NF. Hvad synes du?

Hvis jeg ville øge dataintegriteten for gadenavne, kunne jeg starte med sådan noget.

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.

Du kunne (og burde sandsynligvis) gentage denne proces for bynavne, statnavne (statskoder) og landenavne.

Nogle problemer med din tilgang

Du kan tilsyneladende indtaste et gade-id-nummer for en gade, der er i USA, sammen med lande-id'et for Kroatien. (Det "fulde navn" på en by, så at sige, er den slags kendsgerninger, du sandsynligvis vil gemme for at øge dataintegriteten. Det gælder sandsynligvis også for det "fulde navn" på en gade.)

Brug af id-numre for hver bit af data øger i høj grad antallet af krævede joinforbindelser. Brug af id-numre har ikke noget med normalisering at gøre. Brug af id-numre uden tilsvarende unikke begrænsninger på de naturlige nøgler - en fuldstændig almindelig fejl - tillader duplikerede data.




  1. Sådan fungerer LTRIM() i MariaDB

  2. Kald til udefineret metode Illuminate\\Database\\Schema\\Blueprint::increments()

  3. Er der nogen fordel ved at have en auto-incrementing primær nøgle i en MySQL pivot tabel?

  4. Udfyld JFreechart TimeSeriesCollection fra Mysql DB?