Conceptual stage question:
I have several Tables (Person, Institution, Factory) each has many kinds of Addresses (Mailing, Physical)
Is there a way to create a single Address table that contains all the addresses of all the Entities?
I'd rather not have a PersonAddress and FactoryAddress etc set of tables.
Is there another option?
The amount of data will only be several thousand addresses at most, so light in impact.
My proposal relies on the principle that one entity (person, Institution, Factory, etc) can have multiple adresses, which is usually the case (home, business, etc), and that one adress can be shared by entities of different nature:
CREATE TABLE ADDRESS
(
ID INT IDENTITY PRIMARY KEY NOT NULL,
.... (your adress fields here)
id_Person ... NULL,
id_Institution ... NULL,
id_Factory ... NULL
)
The main limit is that 2 different persons cannot share the same adress. In such a situation, you'll have to go with an additional "EntityAddress" table, like this:
CREATE TABLE ADDRESS
(
ID INT IDENTITY PRIMARY KEY NOT NULL,
.... (your adress fields here)
)
CREATE TABLE ENTITY_ADDRESS
(
ID INT IDENTITY PRIMARY KEY NOT NULL
id_Address .... NOT NULL,
id_Person .... NULL,
id_Institution ... NULL,
id_Factory .... NULL
)
The last model allows you to share for example one adress for multiple persons working in the same institution.
BUT: according to me, the 'better' solution would be to merge your different entities into one table. You will then need:
An Entity Table, made for all entities
An Entity Type table, that will contain the different entity types.
In your case you have at least 3 rows: persons, factories,
institution
If one adress per entity is enough, you could go for the address details as properties of the Entity table.
If you need multiple addresses by entity, you'll have to go with the Addresses Table with an Id_Entity as a foreign key.
If you want to share one adress among multiple entities, each entity having potentially multiple adresses (a many-to-many relation between entities and adresses), then you will need to go for the EntityAddres table in addition to the Entity and Address Tables.
Your choice between these models will depend on your needs and your businness rules.
You need to use abstraction and inheritance.
An individual and institution (I'd call it organization) are really just concrete representations of an abstract legal party.
A mailing or physical address is the concretion of an abstract address, which could also be an email address, telephone number, or web address.
A legal party can be have zero or more addresses.
An address can be belong to zero or more legal parties.
A party could use the same address for multiple roles, such as 'Home' address and 'Work' address.
If a factory is big enough, sub-facilities in the factory might have their own addresses, so you might want to consider a hierarchical relationship there. For example, each apartment in a condo has one address each. Each building in a large factory might have their own address.
create table party (
party_id identity primary key
);
create table individual (
individual_id int primary key references party(party_id),
...
);
create table organization (
organization_id int primary key references party(party_id),
...
);
create table address (
address_id identity primary key,
...
);
create table mailing_address (
address_id int primary key references address(address_id),
...
);
create table party_address (
party_id int references party(party_id),
address_id int references address(address_id),
role varchar(255), --this should really point to a role table
primary key (party_id, address_id, role)
);
create table facility (
facility_id identity primary key,
address_id int not null references address(address_id),
parent_id int null references facility(facility_id)
);
in my opinion ,you should create a pivot table to link Entity with her Address
for exampleinstitution_addresses(id, id_institution,id_address), person_addresses(id,id_person,id_address) etc...
You could very definitely do this. You could have the Address table that has an ID, then Person, Institution and Factory could all have foreign keys to the Address table.
If you need to be able to distinguish what kind of Address it is at the Address level, you could consider adding an AddressType table and having a foreign key to that on the Address table
Example:
CREATE TABLE ADDRESS
(
ID INT IDENTITY PRIMARY KEY NOT NULL,
City VARCHAR(50) NOT NULL,
State VARCHAR(2) NOT NULL,
Zip VARCHAR(10) NOT NULL,
AddressLine1 VARCHAR(200) NOT NULL,
AddressLine2 VARCHAR(200) NOT NULL,
)
CREATE TABLE Person
(
ID INT IDENTITY PRIMARY KEY NOT NULL,
AddressID INT FOREIGN KEY REFERENCES Address(ID)
)
CREATE TABLE Institution
(
ID INT IDENTITY PRIMARY KEY NOT NULL,
AddressID INT FOREIGN KEY REFERENCES Address(ID)
)
...etc
Another basic \ bullet proof system would be to organise your model around:
An Entity Table, made for all entities
An Entity Type table, that will contain the different entity types. In your case you have at least 3 rows: persons, factories, institution
If one adress per entity is enough, you could go for the address details as properties of the Entity table.
If you need multiple addresses by entity, you'll have to go with the Addresses Table with an Id_Entity as a foreign key.
If you want to share one adress among multiple entities, each entity having potentially multiple adresses (a many-to-many relation between entities and adresses), then you will need to go for the EntityAddres table in addition to the Entity and Address Tables.
EDIT: this answer was also merged with the other answer I gave here ... so I do not know if it deserves an upvote!
Related
I have a quick question with respect to many to many relationships in sql.
So theoretically i understand that if 2 entities in an ER model have a M:N relationship between them, we have to split that into 2 1:N relationships with the inclusion of an intersection/lookup table which has a composite primary key from both the parent tables. But, my question here is , in addition to the composite primary key, can there be any other extra column added to the composite table which are not in any of the 2 parent tables ? (apart from intersectionTableId, table1ID, table2ID) a 4rth column which is entirely new and not in any of the 2 parent tables ? Please let me know.
In a word - yes. It's a common practice to denote properties of the relationship between the two entities.
E.g., consider you have a database storing the details of people and the sports teams they like:
CREATE TABLE person (
id INT PRIMARY KEY,
first_name VARCHAR(10),
last_name VARCHAR(10)
);
CREATE TABLE team (
id INT PRIMARY KEY,
name VARCHAR(10)
);
A person may like more than one team, which is your classic M:N relationship table. But, you could also add some details to this entity, such as when did a person start liking a team:
CREATE TABLE fandom (
person_id INT NOT NULL REFERENCES person(id),
team_id INT NOT NULL REFERENCES team(id),
fandom_started DATE,
PRIMARY KEY (person_id, team_id)
);
Yes, you can do that by modeling the "relationship" table yourself explicitly (just like your other entities).
Here are some posts about exactly that question.
Create code first, many to many, with additional fields in association table
Entity Framework CodeFirst many to many relationship with additional information
I have a design dilemma; On one hand (option 1) I only create address table one time but on the other hand (option 2) seems like it would have performance advantages...less joins and less data. What do you guys think?
Option 1 for sure. All your addresses should be in one spot. This shouldn't hinder performance either. You can limit the addresses returned by the WHERE statement when you query the data.
Three customer addresses in one table or in separate tables?
Referencing the aforementioned link: Since you're saying your customer address relationship is modeled as one-to-many, I would use the following example of one address table, an AddressType and a EntityId FK. Using this method would allow for an Entity (client/employee/contact) to have many addresses.
CREATE TABLE Entity
(
ID int not null IDENTITY(1,1) PRIMARY KEY,
Name varchar(60) not null,
EntityType int not null
-- etc
)
CREATE TABLE Address
(
ID int not null IDENTITY(1,1) PRIMARY KEY,
EntityID int not null
CONSTRAINT FK_Entity_EntityID FOREIGN KEY References Entity(ID),
Street varchar(120) not null,
AddressType int not null
-- etc
)
Option 1 is better from a design perspective. One table should have all the addresses - and kept updated accordingly. This way you can easily create relationships between addresses and Client, Employee and Contact (and everything else really) and do queries like: "select everything that lives in X address". Keep in mind that this way you will have to properly maintain your Address table - manage duplicate addresses, make sure the address is correct etc.
On the other hand, in a very simplistic Use-Case where you just want to display a Client, Employee and Contact info, an Address can be a free-text column. This will save you the trouble of properly maintaining addresses.
It all comes down to what you need in the end.
Trying to design part of a database to hold addresses, companies and contacts. I had one design of it in which I've now got the job of 'cleaning' it due to poor design.
Bought a copy of Joe Celko's SQL Programmer Style for reference as I'm coming from a programming angle so I ended up with...
Addresses
street_1_adr varchar(80) primary key
street_2_adr varchar(80)
street_3_adr varchar(80)
zip_code varchar(10) foreign key/primary key > Regions.zip_code
With a check to ensure all addresses are unique to prevent duplicates.
Regions
city varchar(80)
region varchar(80)
zip_code varchar(10) primary key
country_nbr integer foreign key/primary key > Countries.country_nbr
With a check to ensure all regions are unique to prevent duplicates.
Countries
country_nbr integer primary key
country_nm varchar(80)
country_code char(3)
With a check to ensure that only one record exists for all the information.
Companies
company_nm varchar(80) primary key
street_1_adr varchar(80) foreign key > Addresses.street_1_adr
zip_code varchar(10) foreign key > Addresses.zip_code
Extra information
With a check to ensure that only one company with that name can exist at the address specified
Contacts
company_nm varchar(80) primary key/foreign key > Companies.company_nm
first_nm varchar(80) primary key
last_nm varchar(80) primary key
Extra information
But this means that if I want to hook, as an example, an order onto a contact I need to do it with three fields.
Does this look right or have I completetly missed the point?
Firstly, I recommend using integer values for your primary keys
(if using mysql auto_increment is a handy feature, too)
When using your PK (primary key) as a FK (foreign key) in an different table, use the same datatype and don't save names.
You seem to save the company_name in "Contacts" even though you could simply save the ID of the company and get the name via a join-select.
IN your case it is OK, since the name is the primary key (varchar), but what happens when you get the same company name twice (eg Mc Donalds has more than one location)
ERP systems deploy those kind of structures mostly as or near as:
company (id and name)
site (id, name, FK company, additional information like address)
address (mostly referenced directly in site and sometime part of site)
region + country (all of them are "basic" data and referenced by ID in address table)
company table mostly only saves the ID and Name of an company.
site table (with foreign key relation to company) gives the "company" its adresses, legal information, etc.
A couple of thoughts:
First of all, a zip code can represent multiple cities/towns in the same state. Also, one city can have multiple zip codes.
Usually you to not find an address table separate from the entity. In other words, your company table should carry the full address.
The primary keys for the tables are usually unique identifiers or auto-increment numbers separate from the actual names. That way, if a company or contact changes it's name, or a typo was entered and corrected, you do not need to cascade the change to other tables.
You may want to future proof your design by allowing for many addresses and contacts to be added to a company. What you would do is create a many to many relationship by using a junction table (http://en.wikipedia.org/wiki/Junction_table)
Company
--------------
CompanyID (PK)
...
Address
--------------
AddressID (PK)
...
CompanyAddress
--------------
CompanyID (PK)
AddressID (PK)
The CompanyAddress table will allow you to have multiple addresses for each company. You can also do the same for contacts, depending if the contact is associated with the company or the address. Below is another link that talks about how to create the many to many relationship.
http://www.tomjewett.com/dbdesign/dbdesign.php?page=manymany.php
I have a relational database with a Client table, containing id, name, and address, with many phone numbers
and I have an Employee table, also containing id, name, address, etc., and also with many phone numbers.
Is it more logical to create one "Phone Number" table and link the Clients and Employees, or to create two separate "Phone Number" tables, one for Clients and one for Employees?
If I choose to create one table, can I use one foreign key for both the Client and Employee or do I have to make two foreign keys?
If I choose to make one foreign key, will I have to make the Client ids start at 1 and increment by 5, and Employee ids start at 2 and increment by 5 so the two ids will not be the same?
If I create two foreign keys will one have a value and the other allow nulls?
The solution which I would go with would be:
CREATE TABLE Employees (
employee_id INT NOT NULL,
first_name VARCHAR(30) NOT NULL,
...
CONSTRAINT PK_Employees PRIMARY KEY (employee_id)
)
CREATE TABLE Customers (
customer_id INT NOT NULL,
customer_name VARCHAR(50) NOT NULL,
...
CONSTRAINT PK_Customers PRIMARY KEY (customer_id)
)
-- This is basic, only supports U.S. numbers, and would need to be changed to
-- support international phone numbers
CREATE TABLE Phone_Numbers (
phone_number_id INT NOT NULL,
area_code CHAR(3) NOT NULL,
prefix CHAR(3) NOT NULL,
line_number CHAR(4) NOT NULL,
extension VARCHAR(10) NULL,
CONSTRAINT PK_Phone_Numbers PRIMARY KEY (phone_number_id),
CONSTRAINT UI_Phone_Numbers UNIQUE (area_code, prefix, line_number, extension)
)
CREATE TABLE Employee_Phone_Numbers (
employee_id INT NOT NULL,
phone_number_id INT NOT NULL,
CONSTRAINT PK_Employee_Phone_Numbers PRIMARY KEY (employee_id, phone_number_id)
)
CREATE TABLE Customer_Phone_Numbers (
customer_id INT NOT NULL,
phone_number_id INT NOT NULL,
CONSTRAINT PK_Customer_Phone_Numbers PRIMARY KEY (customer_id, phone_number_id)
)
Of course, the model might changed based on a lot of different things. Can an employee also be a customer? If two employees share a phone number how will you handle it on the front end when the phone number for one employee is changed? Will it change the number for the other employee as well? Warn the user and ask what they want to do?
Those last few questions don't necessarily affect how the data is ultimately modeled, but will certainly affect how the front-end is coded and what kind of stored procedures you might need to support it.
"The Right Way", allowing you to use foreign keys for everything, would be to have a fourth table phoneNumberOwner(id) and have fields client.phoneNumberOwnerId and employee.phoneNumberOwnerId; thus, each client and each employee has its own record in the phoneNumberOwner table. Then, your phoneNumbers table becomes (phoneNumberOwnerId, phoneNumber), allowing you to attach multiple phone numbers to each phoneNumberOwner record.
Maybe you can somehow justify it, but to my way of thinking it is not logical to have employees and clients in the same table. It seems you wan to do this only so that your foreign keys (in the telephone-number table) all point to the same table. This is not a good reason for combining employees and clients.
Use three tables: employees, clients, and telephone-number. In the telephone table, you can have a field that indicates employee or client. As an aside, I don't see why telephone number needs to be a foreign key: that only adds complexity with very little benefit, imo.
Unless there are special business requirements I would expect a telephone number to be an attribute of an employee or client entity and not an entity in its own right.
If it were considered an entity in its own right it would be 'all key' i.e. its identifier is the compound of its attributes and has no attributes other than its identifier. If the sub-attributes aren't stored apart then it only has one attribute i.e. the telephone number itself! Therefore, it isn't usually 'interesting' enough to be an entity in its own right and a telephone numbers table, whether superclass or subclass, is usually overkill (as I say, barring special business requirements).
I need to create a table in a relational database using SQL for persons having the columns Name, LastName and so on.
I'll have three different kinds of People: Seller, Buyer and Customer.
Every person has other information/attributes.
Do I need to create a table for each different type of Person or can a single table be used for all three types?
If I used a single table, what if one type of "Person", say Seller, has different attributes from another Person type?
I would create one table Person , with personId as primary key that will contain common properties for all types.(Seller , Buyer , Customer)
Then I would create PersonTypes, a small reference table , that will declare codes for the different types .
Then for each type I would create a separate table with reference to Person table and
PersonType table that includes all the unique properties.
You can create 1 or two tables. Of course you can create 3 tables for each user role. It depend's on what you would like to achieve. Common solution to your question is: create two tables, one for users and one for their roles (examples for mysql:
Create table `person_role` (
id int not null,
roleName varchar(255) not null,
PRIMARY KEY(`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
Create table `person`(
id int not null.
name varchar(255) not null,
lastName varchar(255) not null,
role int not null,
PRIMARY KEY(`id`),
CONSTRAINT FOREIGN KEY(`role`) REFERENCES person_role(`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
Can a seller ever be a buyer or a customer? If they can, put it all in the same table so that you don't have separate copies of the same data.