Is this the correct code to link two tables in a way that one-to-one Relationship in MySQL?
Table1
CREATE TABLE employees (id INT PRIMARY KEY AUTO_INCREMENT,FullName VARCHAR(50))
Table2
CREATE TABLE salary (id INT PRIMARY KEY AUTO_INCREMENT,SalaryNumber VARCHAR(6))
ALTER TABLE salary
ADD FOREIGN KEY (id) REFERENCES employees (id)
ON DELETE CASCADE
ON UPDATE CASCADE
Your example has a number of problems, first of which is that you're linking two non-related auto-incrementing ids. This is a nightmare waiting to happen. If anything happens to get those two ids out of sync, you're dead in the water.
In your example, the 'employees' record would be considered the parent record, upon which the 'salary' record is dependent (i.e. - you might have an employee record without a corresponding salary record, but you wouldn't want a salary record that's not associated with an employee).
Foreign key constraints belong in the child table, as stated in the MySql documentation. As such, what you need in the 'salary' table is a column that looks like this:
EmployeeId INT NOT NULL
Your foreign key would be
ALTER TABLE salary
ADD FOREIGN KEY (EmployeeId) REFERENCES employee (id)
ON DELETE CASCADE
ON UPDATE CASCADE
At this point, you still have a many-to-one relationship, as there is nothing to prevent you from inserting multiple entries into the salary table with the same EmployeeId.
To make this relationship one-to-one, you have to create a unique index on the salary.EmployeeId column.
With this type of relationship, it's important to note that:
you are prevented from inserting a row into salary that doesn't have valid EmployeeId
you are prevented from inserting a row into salary that has a duplicate EmployeeId
when you delete a salary record, the employee record remains untouched.
deleting the employee record results in the deletion of the salary record it is referencing (if you don't want this behavior, change ON DELETE CASCADE to something else)
you are prevented from dropping the employee table until the salary table is empty and dropped.
No, that's a one-to-many relationship. You can have any number of salary rows (including none) linking to a single employee row.
Since the salary is very much an attribute dependent on the employee, I would consider placing it in the employee table itself (unless you have some extra knowledge you haven't shared with us which makes this problematic).
There are ways to enforce one-to-one across separate tables.
For example, you can use triggers to stop duplicates, though some people are adverse to triggers, and this still won't prevent one-to-zero mappings from appearing.
Alternatively, you can use bidirectional foreign keys with a dummy row in both tables (pointing to each other) to allow you to insert in one table at a time.
The way this is done is to insert a row in employees pointing to the dummy salary row.
Then insert the salary row pointing to the newly inserted employee.
Then update the employee row to pint to the newly inserted salary row. All this should happen as a single transaction of course, to maintain referential integrity at the application level.
In order to get the dummy rows in, they'll need to be inserted before the foreign key constraints are added to the schema, otherwise you have a chicken-and-egg situation.
Whether that level of work is actually necessary is debatable, especially when you can enforce one-to-one simply by combining the data into a single table as suggested :-)
Related
I have 2 tables, customer and address. Customer has column address with FK referencing to table address.
Table customer
create table customer
(
id int(11) not null primary key,
...
address int(11) null,
constraint fk_customer_address
foreign key (address) references address (id)
on update cascade on delete cascade,
)
Table address
create table address
(
id int(11) not null primary key,
...
)
I want to have address id in customer table, because in future there will be more tables referencing to address table (Users.address, Business.address, etc) and one table for all addresses because of the same format.
When I delete row in customer table, address row stays in DB.
Is it possible to use this FK relation to delete row in address table, or do I have to delete it manually (programmatically)?
Does this mean that when I delete row from address, customer row is deleted as well?
Edit:
Yes, it does.
You probably don't want customer rows deleted when an address row is deleted. I think the fk would be correct if it was defined as "on delete restrict" or "on delete set null".
So that if you wanted to delete the address record:
on delete set null ➞ All references to that address would be set as null
on delete restrict ➞ You should manually update the address_id it on ALL child tables to some other value (or null) and then delete the parent row
You could somehow avoid the programatic deletion by defining the fk the opposite (that is: address table has a foreign key to customer table, and others)
However, for me this feels somewhat unnatural since you would have to add a new column on the address table for each other table you want to reference. It feels more natural for each table to have the fk of the address.
Another drawback is that it would not allow you to reuse same address on the same table. For example, if two customers would share the same address, you would need to create a row for each of those customers.
With the first solution you would just need a single row on the address table, that could be referenced multiple times on the customer table by different customers.
Of course, your requirements may be a 1:1 relationship. But remember that requirements can change :). And if they do, and you later require to share same address between different rows, you are ready to go with the first solution.
I would use your original approach with a "on delete set null" constraint.
for exmaple, has course relationship table, student id and course id is multi-unique, if i create this relationship table, should i use auto-incr column as PK, or use student id and course id as multi-PK ?
Some people add auto-increment column as PK to just every table.
But I believe it is good to have a multi-column-PK in the case where the table is a relationship table between two or more tables.
On the other hand, it is more effort to delete a multi-column-PK table entry, because you need to give all columns in the multi-column-PK.
Also, check whether your technology stack (programming language) has problems with multi-column-PK.
This is something of a matter of opinion, but I put a synthetic primary key (auto-incremented id) in almost every table I create, including association/junction tables.
Why? Here are some reasons:
If I need to delete or update rows, then the primary key simplifies the process and reduces the change for error.
The primary key captures the insertion order of the rows.
If the row needs to be referred to by another table, then you can refer to it by a primary key.
In some databases, the primary key is used to cluster the data (that is, sort the data on the data pages). An auto-incremented primary key ensures that data goes "at the end". A natural primary key can result in fragmented data.
As an example of the third point, you might have an attendance table that records -- by day -- whether a student attended a class s/he is enrolled in. This could refer to the enrollment table.
Sorry If my question seems too obvious but I still can't find the logic between a relationship of a database model.
ONE TO ONE:
If I have a customer that has only one address where do I have to put my foreign key ?
I first thought it would be a good idea to put it on the customer's table; one column with a foreign key referring to an id of an address.
Because if I need to create a customer, first I would need to create an address.
But I have found some example on the internet
, where they put a foreign key in the address' table, referring to an id of a customer
ONE TO MANY :
And the same question would apply if a customer can have multiple addresses, in which table, should I put my foreign key ?
The foreign key goes on the "many" side.
For example, if a sales_order is associated with at most one customer, and a customer can have zero, one or more sales_order
Then we put customer_id in the sales_order table, as a reference to the (unique) id column in customer table.
This means that we will first need to add a row to customer before we can add a sales_order for that customer. (The foreign key constraint will prevent us from adding a row in sales_order that has a value in customer_id column that doesn't exist in id column of customer.
--
For the special case of a one-to-one relationship, we can implement that the same way as a one-to-many, with an additional UNIQUE constraint on the foreign key column. It really comes down to deciding which direction of the relationship is mandatory, and which is optional. Basically, which table will we add a row to first? The table where we add rows later will have the foreign key constraint referencing the table that we previously added a row...
Suppose I have a table named Suppliers and I want to delete the first row:
delete from suppliers where supplierID = 1
What does it mean to, "Do whatever is necessary to maintain consistency" after the prior query? The Primary Key (SupplierID) was created using the AUTO_INCREMENT.
Well if you are using AUTO_INCREMENT then you cant do what you are thinking as AUTO_INCREMENT keys in database are used to uniquely identify a given row. The best what you can do to find the lowest unused key value is that don't use AUTO_INCREMENT at all, and manage your keys manually.
Also to mention that you can use ON DELETE CASCADE to automatically delete the dependent records in InnoDB database however in MyISAM you have to manually delete them.
Also check this reference.
To maintain cosistency you should use InnoDB endine and foreign keys in dependent tables pointing to Suppliers.supplierID.
Then database will issue an error if you will try to delete record which is referenced in any other table.
http://dev.mysql.com/doc/refman/5.5/en/innodb-foreign-key-constraints.html
ID of first supplier can be found this way:
SELECT MIN( supplierID ) FROM Suppliers
I just starting to use Foreign Keys to enforce the contents of certain Columns and want to be sure I'm putting the Key on the correct table.
In a situation with 2 tables that have a one to many relationship.
e.g.: customers (one) and orders (many).
Where I want to ensure a valid customer number is used in an orders column.
I'm I correct in saying the Foreign Key would placed on the orders table.
e.g.: orders (columnX) references customers (columnX)
Remember that a foreign key is a referential constraint that says the range of values in a table column(s) is being scoped by another table. Specifically, for your example, you would have a customer_id column in your order table that would be a foreign key back to the customer table, meaning that the in all cases you need a valid customer id in order to insert a record in the order table.
Yes, the primary key (typically a customer id) on the one table (customers) should be linked as a foreign key on the many table (orders) in a one-to-many relationship. Each order can belong to only one customer, but a customer can place many orders.