I'm working on a system that is very address-centric and detection of
duplicate addresses is very important. As a result we have broken
addresses down into many parts (DDL below, but I've left out some
reference tables for conciseness), these being state, locality, street,
street number, and address. The breakdown is roughly consistent with
Australian addressing standards, we're working on finalising this.
Because we carry the primary key down each of the levels, this has
resulted in our address table having a very wide primary key (around
170 characters). We refer to addresses from a number of other tables
and although my instinct is to use this natural key in the other tables
I wonder if we should just put a unique index on the natural key,
create a surrogate primary key and use it in the other table. Any
thoughts?
CREATE TABLE dbo.States (
StateID varchar (3) NOT NULL ,
StateName varchar (50) NOT NULL ,
CONSTRAINT PK_AddressStates PRIMARY KEY NONCLUSTERED
(
StateID
)
)
CREATE TABLE dbo.Localities (
Locality varchar (46) NOT NULL ,
StateID varchar (3) NOT NULL ,
Postcode char (4) NOT NULL ,
CONSTRAINT PK_Localities PRIMARY KEY NONCLUSTERED
(
Locality,
StateID,
Postcode
),
CONSTRAINT FK_AddressLocalities_AddressStates FOREIGN KEY
(
StateID
) REFERENCES dbo.States (
StateID
)
)
CREATE TABLE dbo.Streets (
StreetName varchar (35) NOT NULL ,
StreetTypeID varchar (10) NOT NULL ,
StreetDirectionID varchar (2) NOT NULL ,
Locality varchar (46) NOT NULL ,
StateID varchar (3) NOT NULL ,
Postcode char (4) NOT NULL ,
CONSTRAINT PK_Streets PRIMARY KEY CLUSTERED
(
StreetName,
StreetTypeID,
StreetDirectionID,
Locality,
StateID,
Postcode
),
CONSTRAINT FK_Streets_Localities FOREIGN KEY
(
Postcode,
Locality,
StateID
) REFERENCES dbo.Localities (
Postcode,
Locality,
StateID
)
)
CREATE TABLE dbo.StreetNumbers (
StreetName varchar (35) NOT NULL ,
StreetTypeID varchar (10) NOT NULL ,
StreetDirectionID varchar (2) NOT NULL ,
Locality varchar (46) NOT NULL ,
StateID varchar (3) NOT NULL ,
Postcode char (4) NOT NULL ,
StreetNumber varchar (15) NOT NULL ,
BuildingName varchar (100) NOT NULL ,
CONSTRAINT PK_StreetNumbers PRIMARY KEY CLUSTERED
(
StreetName,
StreetTypeID,
StreetDirectionID,
Locality,
StateID,
Postcode,
StreetNumber
),
CONSTRAINT FK_StreetNumbers_Streets FOREIGN KEY
(
StreetName,
StreetTypeID,
StreetDirectionID,
Locality,
StateID,
Postcode
) REFERENCES dbo.Streets (
StreetName,
StreetTypeID,
StreetDirectionID,
Locality,
StateID,
Postcode
)
)
CREATE TABLE dbo.Addresses (
StreetName varchar (35) NOT NULL ,
StreetTypeID varchar (10) NOT NULL ,
StreetDirectionID varchar (2) NOT NULL ,
Locality varchar (46) NOT NULL ,
StateID varchar (3) NOT NULL ,
Postcode char (4) NOT NULL ,
StreetNumber varchar (15) NOT NULL ,
AddressTypeID varchar (6) NOT NULL ,
AddressName varchar (20) NOT NULL ,
CONSTRAINT PK_StreetNumberPrefixes PRIMARY KEY CLUSTERED
(
StreetName,
StreetTypeID,
StreetDirectionID,
Locality,
StateID,
Postcode,
StreetNumber,
AddressTypeID,
AddressName
),
CONSTRAINT FK_Addresses_StreetNumbers FOREIGN KEY
(
StreetName,
StreetTypeID,
StreetDirectionID,
Locality,
StateID,
Postcode,
StreetNumber
) REFERENCES dbo.StreetNumbers (
StreetName,
StreetTypeID,
StreetDirectionID,
Locality,
StateID,
Postcode,
StreetNumber
)
)