are foreign key relationships for address table necessary - mysql

EDIT: I think I worded this wrong. Please read foreign keys as foreign key constraints. I realize I need the client id in the address table, etc.
I have a client table.
id | pref_name | full_name | business_name | etc . . .
I realized the client can have multiple locations/addresses so I have an address table.
id | client_id | name | address1 | address2 | sub_area_id | area_id | province_id | country_id | postcode | etc . . .
Then I realized clients can come from multiple countries so I added:
country table
id | country | code (ISO-2A)
province table
id | name | country_id
area table
id | name | province_id
sub area table
id | name | area_id
So now I realize that I don't need all of sub_area_id | area_id | province_id | country_id in the address table.
From sub_area_id I can get the rest with a join query, however, there will not always be a sub area id. There WILL always be an area id. I guess I do need sub_area_id | area_id but can remove province_id | country_id from the address table
What I am not sure of is do I need foreign keys for the country, province, area, sub_area table with each other?
It seems that if a country is deleted so should all relating data in the other tables, but I am pretty sure that a country will never be deleted. Same for provinces, areas, sub_areas. Is it a waste of time implementing foreign keys?
Also a client might be disabled (not deleted because it would affect historic data) so can a foreign key also disable the client addresses, or is it just not necessary to disable them? Again, its probably not best to delete them as the client may resume later on.
Any suggestions for improvement on my structure?
TIA

Yes definitely you need foreign key to refer the address of client. if you have not the id of the client in address table, you have no way to retrieve address of your client from address table

Related

Is it possible to have a table linking to a table that is linking back to the first table using foreign keys?

Im playing around with MySQL at the moment, learning stuff about database design and wondered something i couldnt find an answer to in Google.
Imagine a table named 'products' with the primary key 'id' and two additional columns named 'name' and 'primary_image_id', where 'primary_image_id' is a foreign key linking to a second table.
The second table is named 'product_images' also with the primary key 'id' and two additional columns this time called 'path' (path to the image) and 'product_id'. 'product_id' is of course a foreign key linking back to the first table.
+----+-----------+------------------+
| id | name | primary_image_id |
+----+-----------+------------------+
| 1 | product_A | 3 |
+----+-----------+------------------+
| 2 | product_B | 6 |
+----+-----------+------------------+
+----+-----------+------------------+
| id | path | product_id |
+----+-----------+------------------+
| 1 | /image_01 | 2 |
+----+-----------+------------------+
| 2 | /image_02 | 1 |
+----+-----------+------------------+
| 3 | /image_03 | 1 |
+----+-----------+------------------+
| 4 | /image_04 | 1 |
+----+-----------+------------------+
| 5 | /image_05 | 2 |
+----+-----------+------------------+
| 6 | /image_06 | 2 |
+----+-----------+------------------+
The idea is to have a table with all product images while only one image per product is the preview image (primary image). Is this type of foreign key linking even possible? And if yes, is it good databse design or should I use an other method?
Thank you in advance!
This is a valid use case and the table design looks good if your intention is to just read data using foreign key like "Get all image paths for product id 1" or "Get primary image of product id 1" or "Get paths of all primary images".
People tend to avoid the cycle of foreign key reference in tables specially if there is a cascade dependency on delete/update events. You need to answer questions like "What should happen to image 2, 3 ,4 if product 1 is deleted" or "what should happen to product 1 if image 3 is deleted".
The answers would help you come with a design that fulfills your requirement
Just use indexes without FOREIGN KEYs.
A more typical approach would be to move the primary flag to the images table. Both of these approaches have the potential for illogical data —
Your way would allow product 1 to name image A as its primary while image A could identify product 2 as its product.
My way would allow products to have 0 or 2+ primary images if the flag wasn’t well-managed.
Depending on how worried you are about either inconsistency, you could try to manage it via triggers or constraints, although MySQL is a little lacking in these areas compared to other DBMSs.
One way to absolutely prevent a problem would be to have the primary flag in the images table, but use it as an int (rank), not a Boolean with a convention that minimum rank is the “primary” — create a unique index on the combination of (product ID, rank) — and access this data via a stored proc or view that could implement the rank convention for you, e.g. select * from images a where product_id = whatever and does not exist (select 1 from images b where a.product_id = b.product_id and a.rank > b.rank).
Seems like overkill, but you need to be the judge how important potential data integrity issues are for your application.

Multi-language database birthplace design

I have a database that has to work with 2 countries, IT and RO.
I have a table called User, that contains also the birthplace.
User
| id | name | surname | birthplace |
| 1 | Test | Test | New York |
I also have 2 tables for the birthplace, one for the IT ones and one for the ROs. I cannot store all the cities in one table because IT and RO have a different gerarchy (region, province, district...). So my first thought was to do a birthplace field for each country, like this:
User
| id | name | surname | birthplaceIT | birthplaceRO |
The problem is that every time a nation is added, I'd have to modify the database and the application. On the other side, I cannot make a "birthplace" table because the IT and RO addresses are not compatible.
So, I cannot do this:
Birthplace
| idUser | country | city |
Because I cannot refer "city" to both the IT cities table and the RO ones.
Suggestions?
EDIT. In my PHP application i'm using Symfony with Doctrine, an ORM, so I NEED the Foreign Key constraint between the User and the CityID!
Instead of storing birthplace in User table, change it to let's name it birthplace ID - it can be simply integer but you can do something more sophisticated and use unique codes (your own or maybe there are "proper" geographical codes).
Then you can have table for each country specific birthplace and join tables based on birthplace ID. This way you can keep each country specific geographical hierarchy in its own table. If you need to add another country - you simply create another table for that country and join it with User.

Extending a table (one to one relationship)

I have a Users table that belongs to a Role, and has one Server or no one (depends on role), but should to have a Server table with user_id field or should I put all Server info in Users table and when the role hasn't Servers, the fields will be null?
I just think that if a User have one server (or not), this shouldn't be a new row in Servers table, maybe if the user_id field be unique, then it will be correct, I don't know.. I'm confused.
Just explain to me which is the best way to build this thing.
-- edit
This is my tables actually
Roles
id (PK) | name
1 | Administrator
Users
id (PK) | role_id | name
1 | 1 | Juliano
Servers
id (PK) | user_id (UNIQUE) | name
1 | 1 | Test
I don't know.. in servers, user_id should be UNIQUE or PK?
ONE TO ONE Relation , Then put the server in the user table.
Users Table:
ID(Pk)
RoleID
Name
ServerID

Track data change (Update/Delete) in MySQL

I have a db schema where user data is stored using foreign key references , these foreign keys are admin defined . Also , there is some data which is stored without primary keys , however I have other constraints in place to avoid redundancy and other issues .
Due to the requirements of the application when a user 'updates' their info I have to delete all user records from the 'updated' table and reinsert all the user's records again . (I have looked into all other options)
Now because of my search solution (solr) , I need to track changes to the user data (updates/deletes) . I am planning on having a view to compare the last committed data to the real time data . I am fearful of how sustainable it would be to have a stored procedure running every 20 minutes or so , is there a better way of tracking data with SQL ?
You could create a change table that contains the same columns as the original table plus another column called "UpdatedOn." Then set up a trigger to write to this change table the original values when the original table is changed.
Example:
Original Table:
Name | Address | City
Jane Doe | 1 Main St. | New York
Change to Original Table:
Name | Address | City
Jane Doe | 2 Smith St. | Dubuque
...which triggers an insert to the Change Table:
Name | Address | City | UpdatedOn
Jane Doe | 1 Main St. | New York | 2012-01-01
There is information about using triggers in mysql here: http://dev.mysql.com/doc/refman/5.0/en/triggers.html

How to handle tables with multiple parents

I'm having trouble modeling a particular database structure I'm working on. To be short, considering the following:
A webpage can have one or more threads on it
A thread consists of one or more comments
Comments can have one or more complaints filed against it
Complaints can also be filed against the thread as a whole
Complaints can also be filed against the page
I can't quite figure out how to model this at the DB level. The first three are easy:
webpage
----------
id
name
thread
---------
id
page_id
name
comment
--------
id
thread_id
name
But if I wanted a single table of complaints, how would one model that? I don't think you would want to do:
complaint
----------
id
page_id
thread_id
comment_id
If you ever added a new object type, like picture, you'd have to add more columns to the complaint. Is there a better way to do this, or is at as good as it gets?
Thanks in advance,
- Anthony
I would create the complaint as an entity in it's own right, then have link table between all the different things it can be associated with.
So, I'd have the following tables ...
complaint
compliant_comment_link
complaint_thread_link
complaint_page_link
This is a slightly different variation on Waleed's solution. As with all things like this, there are many ways to solve it :)
The advantage of this approach is that you can have foreign keys to maintain data integrity. The disadvantage is that whenever you need to have complaint against a new "thing" you will need a new link table, but I suppose you'd have to create a new "thing" table anyway.
One solution off the top of my head is to have a table:
ObjectType
-------------------
| id | name |
-------------------
| 1 | Webpage |
| 2 | Thread |
| 3 | Comment |
-------------------
Then your complaint table can be as follows:
----------------------------------------
| id | object_type_id | objectid |
----------------------------------------
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 2 | 1 |
---------------------------------------|
Of course this could add additional work later on when querying the complaint table and joining with the others, but that all depends on what you want to query.
Another approach is to have a new entity table that has a supertype/subtype relationship with the 3 tables (webpage, thread, comment):
entity
----------
id (PK)
webpage
----------
id (PK)
name
FOREIGN KEY id REFERENCES entity(id)
thread
---------
id (PK)
page_id
name
FOREIGN KEY id REFERENCES entity(id)
comment
--------
id (PK)
thread_id
name
FOREIGN KEY id REFERENCES entity(id)
complaint
----------
id (PK)
entity_id
FOREIGN KEY entity_id REFERENCES entity(id)
This way, creating of a new webpage (or thread or comment) or deleting one will be slightly more complicated (inserting or deleting a new row in two tables than one.)