开发者

Database design SQL Server

Say I hav开发者_运维技巧e a database with multiple entitles like person, company, conference for which you have to keep track of say addresses. We can have multiple addresses for the same entity (person). One approach is to have a separate address table for each entity (person_address etc). Another approach is to have an address table which has primary key (Entity,id,address_type). In this approach we cannot use foreign keys from address table to entities .

So what is the better approach. Is there another way to do this ?

thanks


At a logical modeling POV your descriptions highlights the fact that the entities like person, company, conference etc have a common trait: they have zero, one or more addresses. If you would model this as a class hierarchy, perhaps you would create an Addressable class and have person, company and conference inherit from this Addressable class. You can apply the same reasoning to your data model and have an addresable table with an addressable_entity_id. The person, company, conference entities would 'inherit' this table. There are three established ways to implement table inheritance:

  • Class Table Inheritance
  • Single Table Inheritance
  • Concrete Table Inheritance

So you could model your tables like this:

create table Addresses (AddressId int not null identity(1,1) primary key, ...);
create table Addressable (AddressableId int not null identity (1,1) primary key, ...);
create table AddressableAddress (
    AddressId int not null,
    AddressableId int not null,
    constraint AddressableAddressAddressId
        foreign key (AddressId) references Addresses(AddressId),
    constraint AddressableAddressAddressableId
        foreign key (AddressableId) references Addressable(AddressableId));
create table Person (PersonId int not null identity(1,1) primary key,
     AddressableId int not null, 
     ...,
     constraint PersonAddressableAddressableId
         foreign key AddressableId references Addressable (AddressableId));
create table Company (CompanyId int not null identity(1,1) primary key,
     AddressableId int not null, 
     ...,
     constraint CompanyAddressableAddressableId
         foreign key AddressableId references Addressable (AddressableId));

Of course you have to find the right balance between absolute relational normal form and actual usability. In this scheme I propose for instance in order to insert a new Person one has to first a row in Addressable, get the AddressableId and then proceed and insert the person. This may or may nor work. BTW, there is a way to do such an insert in one single statement using the OUTPUT clause to chain two inserts:

insert into Addressable (AddressableType)
 output  inserted.AddressableId, @FirstName, @LastName 
 into Person (AddressableId, FirstName, LastName) 
values (AddressableTypePerson);

But now is difficult to retrieve the newly inserted PersonId.


Technically if two people live at the same address you would not be completely normalized if there was simply a single one-to-many detail table for the row in TBLPerson called TBLAddress However, if you want just one instance per physical address you will incur the overhead of a many-to-many relation table of TBLPersonAddresses which FK's to TBLAddress

I would say that unless you expect multiple people at the same address to be the norm that I would simply have the TBLAddress with column personID as a detail to the TBLPerson

EDIT: And I tend to always use surrogate keys unless I have a specific reason not to do so.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜