I have this situation:
MANAGER (ManagerID, Salary, .... , email)
PROJECT (ProjectID, ..., Date)
Since there is relationship M:N between Manager an project, I'll have a third table:
Manager_has_Project( ManagerID, ProjectID )
where ( ManagerID, ProjectID ) is the compound PK for Manager_has_Project
Let's suppose we have to delete a Manager who has created some projects from our database: SQL won't make us do that. We could add the constraint on the fk ManagerID in the child table "ON DELETE CASCADE", but in this case we will lose information about, for example, how many managers worked for a project. The alternative is "ON DELETE SET NULL" but, since ManagerID is part of the compound pK of Manager_has_Project, we can't set a PK as null.
What would recommend to do?
If you want to to keep the information, use soft deletes rather than actually removing the rows.
That is, add a column, say is_deleted or deletion_datetime that indicates that a Manager has been deleted. Then you can keep all the information, even about "deleted" managers.
You can use views so "normal" queries would only return managers who are not deleted.
Related
My question can be demonstrated using the classic "employees" self referencing table, where manager_id is the FK related to the employee_id (PK). Another table is "authorizations".
What if authorizations are only relevant to managers and not to non-managers?
Assuming I create a junction table of "manager authorizations", can this table connect to employees.manager_id even though it's not unique?
Or must I separate managers to another table, even though they have the exact same attributes as non-managers?
Look at this structure Employees Structure. It manages a complex situation (a manager is responsible of one or more departement) and records are historical (from_date, to_date).
Try to modify this structure as follow:
departments becomes authorizations
dept_emp becomes the associative table auth_emp
remove dept_manager
A FK must always refer to a PK so connecting auth_emp to employee by manager_id is not possible (think to null references).
The decision to split or not employees that are manager to another table depends on your requirements (think about this: when a employee becomes a manager? An employee is a manager when at least another employee refers to him?).
If you want force the constraint that an employee_id registered in auth_emp refers to a manager you can use trigger on employee table. Obviously the trigger logic depends on your requirements.
Is there any sense in using two foreign key to the same parent table, to avoid inner join?
table: user_profile
id1, userid, username, firstname
table: user_hobby1
id2, userid(fk), hobby, movies
table: user_hobby2
id3, userid(fk), firstname(fk), hobby, movies
I want to select all firstname and hobby from the above table. I am not sure if user_hobby1 or user_hobby2 is the best design in terms of performance? One adds extra foreign key and another requires join.
Query1 :
Select firstname, hobby
from user_hobby2;
Query2 :
Select p.firstname, h.hobby
from
user_profile p
inner join user_hobby1 h on u.userid=h.userid;
Copying the value of an attribute from the user table into the hobby table isn't a "foreign key", that's redundancy.
Our performance objectives are not usually met with an approach of avoiding JOIN operations, which are a normal part of how relational databases operate.
I'd go with the normalized design as a first cut. Each attribute should be dependent on the key, the whole key, and nothing but the key. The "firstname" attribute is dependent on the id of the user, not the hobby.
Sometimes, we do gain performance benefits by introducing redundancy into the database. We have to do that in a controlled way, and make sure that we don't get update anomalies. (Consider what changes we want to apply if the value of "firstname" attribute is updated... do we make that change to the user table, the user_hobby table, or both.
Likely, "firstname" is not unique in the user table, so we definitely don't want a foreign key referencing that column; we want foreign keys that reference the user table to reference the PRIMARY KEY of the table.
There's no point in having two foreign keys defined between user_hobby and user, if a user_hobby is related to exactly one user. We only need one foreign key... we just store the id from the user table in the user_hobby table.
if you have two FK in user_hobby2 then you can only ensure that userid and username exist in user_profile, but you have no way to ensure which userid goes with a given username.
if you make (userid, username) a composite FK, then you'll guarantee the consistency of each tuple, but composite FK are generally more complicate to deal with. Depending on the behavior for update and delete cascades I've seen mysql triggering them both and refusing to delete from the parent.
Besides... what's the point of keeping that composite FK? It will only help you when you update or delete from user_profile, but won't help you copy the data when you insert new users or new hobbies for a user.
The join you are trying to avoid is very cheap. Just go with the first approach. It's easier to maintain and will help you keep your data consistent and normalized.
I just started learning databases. My professor mentioned the term "referential integrity" and I'm trying to understand it.
Here's my understanding. If I have
Table Manager: Manager_id , Manager_name
Table Employee: Employee_id , Manager_id , Employee_name
Manager_id is the primary key for "Manager table" & foreign key for "Employee table"
If I delete/update any Manager_id from Manager then all the entries having that manager id will get deleted/updated. Thats cascading update or delete.
But what if I try to delete or update manager_id in the "employee table" ? Will it correspondingly delete the entries from Manager table?
If I delete/update any Manager_id from Manager then all the entries
having that manager id will get deleted/updated. Thats cascading
update or delete.
This happens only if you have defined UPDATE/DELETE rules for Foreign Key. By default, cascading UPDATES/DELETES are disabled as it might cause unexpected changes in your data.
But what if I try to delete or update manager_id in the "employee
table" ? Will it correspondingly delete the entries from Manager
table?
It will delete only single employee as related manager could be referenced by some other employee as well.
The 'cascade' part goes from the Primary Key towards the Foreign Key, but not the other way around.
When you delete Manager1 let's say, then it makes no sense for Employee1 to have Manager1 as a manager, since they are no longer defined.
But when you change Employee1's manager from Manager1 to Manager2 - then that is still fine assuming both managers still exist.
I am building a web based application for a big company and i have a question about the database part. Lets first introduce you to the situation:
There are 4 very tables that are connected with foreign keys:
Table 1: roadlists
roadlist (roadListNumber, vehicleId, driverId, date, start, end, fuel,...)
roadListNumber - primaryKey
vehicleId - foreignKey
driverId - foreignKey
Table 2: drivers
drivers(driverId, firstName, middleName, lastName, and so on...)
driverId - primaryKey
Table 3: vehicles
vehicles(vehicleId, group, type, model, gpsDevice, and so on...)
vehicleId - primaryKey
Table 4: cargo_zones
cargo_zones(zoneId, name, permiter, area, latitures, longtitudes, and so on...)
zoneId - primaryKey
Table 5: roadLists_cargoZones_mapping
roadLists_cargoZones_mapping(roadListNumber, zoneId, spentFuel, tkm, mcm,...)
roadListNumber - foreignKey
So here is the problem:
If i delete a driver from drivers table the value in the roadlists table will be set to NULL or the whole row will be deleted based on the constraints. In the first case if it is set to NULL if somebody lists all the reports for some date he will not be able to see the driver's name who was on duty because its id does not link to any row in the drivers table. In the seconds case if the whole row is removed from the roadlists table the system loses important data.
So how do i deal with this kind of situations?
The preferred way (but not the only way):
Mark a driver as deleted (have a boolean deleted column, or call it IsActive), without actually deleting the driver or related information.
This way you can still historically report. One way to approach this is create views over the table; one view for AllDrivers and one for ActiveDrivers and join to these rather than the table directly, or just add the IsActive predicate to your query WHERE clauses.
The way you deal with this situation is DON'T DELETE the row from the Driver table.
This is information you want to keep. So, don't remove it.
What you might need is a way to mark the Driver row as inactive, archived, unavailable, or whatever. You've got a status change, NOT a delete.
Any queries where you need that driver EXCLUDED, you can add a predicate (a condition in the WHERE clause) to exclude those rows.
I'm developing a helpdesk-like system, and I want to employ foreign keys, to make sure the DB structure is decent, but I don't know if I should use them at all, and how to employ them properly.
Are there any good tutorials on how (and when) to use Foreign keys ?
edit The part where I'm the most confused at is the ON DELETE .. ON UPDATE .. part, let's say I have the following tables
table 'users'
id int PK auto_increment
department_id int FK (departments.department_id) NULL
name varchar
table 'departments'
id int PK auto_increment
name
users.department_id is a foreign key from departments.department_id, how does the ON UPDATE and ON DELETE functions work here when i want to delete the department or the user?
ON DELETE and ON UPDATE refer to how changes you make in the key table propagate to the dependent table. UPDATE means that the key values get changed in the dependent table to maintain the relation, and DELETE means that dependent records get deleted to maintain the integrity.
Example: Say you have
Users: Name = Bob, Department = 1
Users: Name = Jim, Department = 1
Users: Name = Roy, Department = 2
and
Departments: id = 1, Name = Sales
Departments: id = 2, Name = Bales
Now if you change the deparments table to modify the first record to read id = 5, Name = Sales, then with "UPDATE" you would also change the first two records to read Department = 5 -- and without "UPDATE" you wouldn't be allowed to make the change!
Similarly, if you deleted Department 2, then with "DELETE" you would also delete the record for Roy! And without "DELETE" you wouldn't be allowed to remove the department without first removing Roy.
You will need foreign keys if you are splitting your database into tables and you are working with a DBMS (e.g. MySQL, Oracle and others). I assume from your tags you are using MySQL.
If you don't use foreign keys your database will become hard to manage and maintain. The process of normalisation ensures data consistency, which uses foreign keys.
See here for foreign keys. See here for why foreign keys are important in a relational database here.
Although denormalization is often used when efficiency is the main factor in the design. If this is the case you may want to move away from what I have told you.
Hope this helps.