MySQL relationship issue - mysql

I've two tables structure is below
person (id, fname, lname, ph, mob, dob, email)
address (id, address1, address2, address3, town, county, postcode)
person_address (id, person_id, address_id)
I've have a issue here, if one person have more than one address how would i work out which is active or current address, should i add a direct link of address table such as person (id, fname, lname, ph, mob, dob, email, address_id)
or should i add a link to person_address link to person table person (id, fname, lname, ph, mob, dob, email, person_address_id)
any idea

Presumably, a person can have only one current address. If so, you should add a column into the person table, called something like CurrentAddress.
If you require a current address, you can even declare CurrentAddress to be NOT NULL.
If a person could have more than one current address, then use a flag in person_address.
Now, if you want the current address to be the most recently inserted address, you can use a trigger to reset the value on each insert. Or, if your database is not too big (thousands of rows, not millions of rows), you can calculate it on the fly by choosing the person_address record with the most recent creation time.
EDIT:
#Joanvo's point is a good point. You can fix it by adding a foreign key constraint in person referring to to person_address. You will have to create a unique constraint on current_address(person_id, address_id) and use that for the foreign key.

You should add a bit in the person_address table to indicate if it is the current address or not. Make sure there are not more than one current addresses via sql or code checks:
person_address (id, person_id, address_id, current)

If you add a reference of the person_address table into the person table that would create a circular dependancy between person_address and the person table, since the person_address table already encapsulates a reference to the person table. Thing that you should never do when dealing with database design.
Now, If you want a clean design, I would recommand to a reference from the adress table to the person table like you did in your first example. So your design solution will be like follows:
person (id, fname, lname, ph, mob, dob, email, address_id)
EDIT:
Or a solution will be a current_flag in your person_adress table, so when you want to have the current address for a person, you will search for the person_adress entry that has the current_flag set to 1 for that person.
person_address (id, person_id, address_id, current_flag)

Related

Better way to organize DB relations?

Lets say I have tables:
company (id, name)
user (id, username)
employee (id, user_id, company_id, position) -- position is an integer enum
department (id, title, company_id)
And I also need to store relation user is a manager of department
One department may have many managers, and user may be manager in many departments
So I have two ways to do that:
Make manager table look like this: manager (employee_id, department_id)
Or manager(user_id, department_id)
in first case I guarantee integrity (only employee might be a manager), but in order to reach users fields from department I'll have to do three joins department -> manager -> employee -> user.
In second case I have one less join but I have to ensure integrity manually (delete manager, when employee gets deleted etc..)
I can think of another one approach, it's composite keys on employee and manager tables, but since I work with Doctrine 2 it does not recommend to use it.
So how you think will be better? Or might be something is wrong in the first place? Also where should I lookup next time to be able to solve it by my own? How should I test it?

Writing a update statement to alter this database?

I am very stuck about how to write an update statement for this database. The instructor for the test at 29/04/2015 10:00 has changed to be the instructor with a Mini One. What would the SQL command be to make this change?
Here is the relational Schema for the database.
Client (clientNo, forename, surname, gender, address, telNo, proLicenceNo)
Instructor (instructorID, forename, surname, gender, address, telNo, licenceNo, carNo)
Car (carNo, regNo, model)
Lesson (clientNo, onDate, atTime, instructorID)
Test (clientNo, onDate, atTime, instructorID, centreID, status, reason)
Centre (centreID, name, address)
Primary keys are in bold and foreign keys are in italic. No foreign keys are allowed to be null.
Thanks for any help I really appreciate it! :)

Best practice for designing user/roles/people in database

I would like to know how is the best way to design tables in database in the next scenario:
I have companies, clients and employees with some common fields and others are totally different. The most important thing is all of them have a username, email and password to be able to login in an admin system. Then I would like to know the best way to organise all that data in tables. At the moment I was thinking
user (id, role_id, email, username, password)
user_role (id, parent_id, name) -- company|client|employee
user_role_link (user_id, role_id)
company (id, user_id, name, ...)
client (id, user_id, first_name, last_name, ...)
employee (id, user_id, first_name, last_name, start_date, end_date, ...)
That way I have only to check the table user when the user login but I don't know if is a company, client or employee (I have to check all tables).
I am a little bit confuse about this then I don't know how to do it...
Thanks for your help.
How about getting rid of the user_role and user_role_link tables, since you already have the required information in the other tables and then you don't have to maintain all these links:
user (id, email, username, password)
company (id, user_id, name, ...)
client (id, user_id, first_name, last_name, ...)
employee (id, user_id, first_name, last_name, start_date, end_date, ...)
Note there is no such thing as "role" anymore, because clients, companies, and employees "have a" user. So what you have is an aggregation model in the above.
Going further than this, what you might be proposing is an object-oriented inheritance approach. Seen through that filter, you would just have user, company, client, and employee, where the latter three are "kinds of" users. In fact company, client and employee can actually share the same IDs with user in this case since they are essentially the same object! They are all derived from user and are users. (But unless you know what you're doing I wouldn't necessarily advise this option.)
So those are the two options I see here - aggregation or inheritance.
Notice if you lose the link tables, you can still figure out which type of object you have by doing an outer join on all three of the tables and checking which table's ID field comes back with an ID as opposed to a null. Once you know the type you have, the type-specific code has very straightforward querying, with just a single join, user to whichever derived table. For example, let's say you know you have a client, the client code can query directly against the client table and just do one join to user and that's all that's needed.
For more information on some common ways of laying out object-oriented data in a conventional database, the reference material on Python's SQLAlchemy provides some general approaches:
http://docs.sqlalchemy.org/en/rel_0_9/
SQLAlchemy is a library that is specifically designed to aid with object-relational mapping issues, so you can see how they do things. I'm suggesting this as a reference for that reason, and not for any Python connection.
This is my way. I create a Profile table... and users/employs/clients use it.
And an user should be get a role. If do you want create users groups, you need create a Users Group Table.
Table "user":
id_user
date_created
date_deleted
id_role
id_profile
username
alias
password
password_question
password_answer
Table "role":
id_role
date_created
date_deleted
name (35)
description
Table "permission":
id_permission
date_created
date_deleted
name
description
Table "permission_assigned":
id_permission_assigned
date_created
date_deleted
id_permission
id_user
id_role
Table "user_session":
id_user_session
id_user
logon_date
logoff_date
ip_address (45)
user_agent (413)
Table "profile":
id_profile
date_created
date_deleted
first_name (35)
last_name (35)
sex
email (254)
phone (15)
birthday
address (40)
id_country
id_state
id_city
zip_code (10)
description

insert values into two tables at the same time - one to one relationsship

I have two mysql database table. They have one-to-one relationship between each others. They are empty. I can't insert value to anyone. Each one has a foreign key of another one. I'm planning to insert value to them in the same time. But, I didn't find which sql query is necessary. What is your offer?
Thanks
one-to-one relationship example:
student: student_id, first_name, last_name, address_id
address: address_id, address, city, zipcode, student_id
For 1 to 1 table relationship, that doesn't mean you have to put their PK on each other, instead people usually decide which FK goes to another table and that's all. From what you did, that shows Many to Many table relationship, and the right schema would be creating a new table that has FK to those 2 tables.
Details:
If 1 student can have MANY address and 1 address can be lived by MANY student, then the schema is:
student: student_id, first_name, last_name, address_id
address: address_id, address, city, zipcode, student_id
student_address: student_id (FK), address_id (FK)
If 1 student can have only 1 address and 1 address can be lived only by 1 student, then the schema is:
student: student_id, first_name, last_name, address_id, address, city, zipcode
You don't need address_Id in the student table. What if the student is homeless? What if a student has more than one addresss? He/she might have a mailing address a local address in the college town, and a home address.
And even for students with only one address, you can get that address by querying the address table using student_Id.
Select * From addresses where student_id = [Whatever his/her id is]
Even more generally, multiple students might live at the same address. Neither table should have a FK to the other. There should be an address table, with addressID, a Student table with studentId, and a third table that contains just studentId and addressId to indicate the association between one student and one address. The PK for this table should be composite (using both StudentId and AddressId)
That is not how MYSQL works. It sounds like your database design needs to be reworked. You can't have a circular foreign keys like that. You can only insert into one table at a time.
Looking at your tables, the student should have Student Id as the primary key, and a foreign key relationship to the address table. The student Id in the address shouldn't be in that table.

Better way to reference foreign key in database

can you suggest the best practices for database optimization?
Here is my database schema,
group(id, name, status)
users(id, group_id, parent_id, username, password)
company(id, name, address, phone)
agent(id, agent_code, name, address, phone)
In this schema i have four kinds of user group as super admin, company user, agent user and end user.
What is the best way to refer the users of each entities(company, agent)?
I have two options
A. Foreign key in users table as company_id and agent_id
users(id, group_id, parent_id, company_id, agent_id, username, password)
B. Foreign key as user_id in the company and agent table
company(id, user_id, name, address, phone)
agent(id, user_id, agent_code, name, address, phone)
I am using mysql as database and using cascade reference.
When I delete a company/agent, associated users are automatically deleted as per option A. But in case of option B I must run second query to delete the associated users of a company/agent. So what do you suggest???
UPDATE:
Forgot to mentioned about child users. A user of a company/agent can have sub users, referred by parent_id in the users table.
Option A sounds good.
Example :- as their can be suppose 100 users associated with just 5 companies and so can delete the single user in a single query...