sql >> Databasteknik >  >> RDS >> Mysql

Normalisering gör kopplingar över flera tabeller svåra

Jag tänker inte prata om felstavningar. Eftersom du importerar data hanteras felstavningar bättre i en mellanställningstabell.

Låt oss titta på denna något förenklade 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');

Även om många människor är övertygade om att postnummer bestämmer stad och delstat i USA, så är det inte fallet. Postnummer har att göra med hur transportörer kör sina rutter, inte med geografi. Vissa städer går över gränserna mellan stater; enstaka postnummerrutter kan korsa delstatslinjer. Till och med Wikipedia vet detta , även om deras exempel kan vara inaktuella. (Leveransvägar ändras hela tiden.)

Så vi har en tabell som har två kandidatnycklar,

  • {store_name} och
  • {street_num, street_name, city, state_code, zip_code, iso_country_code}

Den har inga icke-nyckelattribut. Jag tror att den här tabellen är i 5NF. Vad tycker du?

Om jag ville öka dataintegriteten för gatunamn skulle jag kanske börja med något sånt här.

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 kan (och förmodligen borde) upprepa denna process för stadsnamn, delstatsnamn (delstatskoder) och landsnamn.

Några problem med ditt tillvägagångssätt

Du kan tydligen ange ett gatu-id-nummer för en gata som ligger i USA, tillsammans med lands-ID för Kroatien. (Det "fullständiga namnet" på en stad, så att säga, är den typ av fakta du förmodligen vill lagra för att öka dataintegriteten. Det är förmodligen också sant för "fullständiga namnet" på en gata.)

Att använda id-nummer för varje databit ökar avsevärt antalet anslutningar som krävs. Att använda id-nummer har inget med normalisering att göra. Att använda id-nummer utan motsvarande unika begränsningar på de naturliga nycklarna – ett helt vanligt misstag – tillåter dubbletter av data.




  1. Migrera från Oracle till MySQL

  2. Behöver hjälp med beräkning med två datamängder med Expression SSRS

  3. Hur ansluter man till en fjärrbaserad MySQL-databas med Java?

  4. MariaDB Connector/Python Beta nu tillgänglig