some join insert into same table foreign key - mysql

I have one table with some foreign keys of other tables. I dont know how insert normal values and values of foreign keys.
I want insert one row with one column of one foreign key and two columns of other foreign key.
The question is how i do the insert in table 'user'?
My tables are:
table CITY
id_city (pk) | nom_city
--------------------------------
1 new york
table FOOD
id_food (pk) | nom_food
--------------------------------
1 fish
2 meat
And I want to create this table:
table USER
id_user (pk) | nom_user | id_city(fk) | id_food(fk) | id_food(fk)
---------------------------------------------------------------------------------
1 ana 1 1 2
Thanks and sorry for my english :)

You use a simple insert statement. The statement is not affected by the foreign keys however an error will be thrown if the foreign keys are violated. i.e they do not exist in your other table.

Related

One to many relationship MYSQL

I'm new to mysql and am trying to link two tables and am not sure how, i have a products table with a list of products in a restaurant, the column in this table are
ID(primary key)
name
price
The other table is called extras, this table contains extra things that you can add to your order but are optional, for when buying chicken you have an option of spicy and non spicy,
Some products have more than one extras, for instance a product can have the option of choosing three extras.
The extras table at the moment only has
ID(primary key)
name
not sure how to link the two or where to put foreign constraints.
UPDATE
Same extra may also belong to numerous products
A joining/linking table usually uses many-to-many relationships by joining the 2 parent tables/primary keys to allow many products to have many extras or no extras at all.
so for example:
eg:
Product IDs (primary keys) are: 1, 2, 3
Product names are: chicken wings, chicken breast, chicken fillet
Extras IDs (primary keys) are: 1, 2, 3
Extras names are: mild, medium, hot
Wings, breasts and fillet have the option of all three of the extras, so the product_extras table would end up looking something like this:
product_extras_id | product_id | extras_id
------------------------------------------
1 | 1 | 1
2 | 1 | 2
3 | 1 | 3
4 | 2 | 1
5 | 2 | 2
6 | 2 | 3
7 | 3 | 1
8 | 3 | 2
9 | 3 | 3
With products having many extras and extras applying to many products this is actually a many to many relationship.
create table products(ID int auto_increment Primary Key,
Name varchar(50),
Price decimal(6,2));
create table extras(ID int auto_increment Primary Key,
Name varchar(50));
create table product_extras(Product int Not Null,
Extra int Not Null,
FOREIGN KEY(Product) References products(ID) ON DELETE CASCADE,
FOREIGN KEY(Extra) References extras(ID) ON DELETE CASCADE);
Something akin to this should work for you, though you may want to change the datatypes based off preference and what data actually needs to go in there.
In your case one product may have many extras(1 to many) and many products may be having same extra thing(many to 1). Thus, this is a many to many relationship and for such relations we need 3 tables.
CREATE TABLE products (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50),
price DECIMAL(10.2)
);
CREATE TABLE extras (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50)
);
CREATE TABLE products_extras (
id INT PRIMARY KEY AUTO_INCREMENT,
pro_id INT,
FOREIGN KEY(pro_id) REFERENCES products(id),
ext_id INT,
FOREIGN KEY(ext_id) REFERENCES extras(id)
);

Foreign key referenced value used only once

I have this kind problem regarding sql:
Table 1: ID_1 (Primary Key) | NAME | LASTNAME | EMAIL...
Table 2: ID_2 (Primary Key) | NAME2 | LASTNAME2 | EMAIL...
Normally using constraints it is possible to make as column in TABLE 2
(NAME 2 for example) as a foreign key for NAME the first TABLE 1.
The general relation would be one-many. That's one value from column NAME in TABLE 1 used many times in column NAME2 in Table 2.
Now what I want to achieve is that making the rule one-to-one, so I cannot have duplicated values of NAME from table TABLE 1 in TABLE 2.
Does it require triggers or it can be set by constraint when creating the tables?
Steps to achieve this:
Create foreign key constraint
Create unique constraint
This can all be done while creating the table.
CREATE TABLE table2 (
...,
name2 varchar(255),
FOREIGN KEY (name2) REFERENCES table1(name),
UNIQUE (name2)
);
If you already have the table, use ALTER TABLE instead.
When trying to insert a row with value of name2 that is already in a table, an error will be raised.
Yes it can be set by constraint. You can have foreign keys and unique keys on the same field. The unique constraint will guarantee there is only one record with one reference to the primary table (from that foreign table)

Can a foreign key refer to the primary key of its own table?

I am creating a MySQL employee database for work and I want it to store the supervisor of the employee.
Suppose I have a table called 'employee' with the fields 'id', 'first_name', 'last_name', and 'supv_id' where 'id' is the primary key and 'supv_id' is a foreign key that refers to and employee ID.
Currently I have 'supv_id' as a foreign key that points to a separate table 'supervisor'. This table simply consists of 'id' and 'empl_id' which points back to the employee table. However, if there is a way to simply make 'supv_id' in 'employee' to point to 'employee.id', this would eliminate the need of my 'supervisor' table altogether. Here is an example:
+----+--------+-----------+---------+
| id | f_name | l_name | supv_id |
+----+--------+-----------+---------+
| 1 | Han | Solo | NULL | //Or 0?
| 2 | Luke | Skywalker | 1 |
+----+--------+-----------+---------+
In short, I want 'supv_id' to point to another employee. Does this make sense? How would I go about doing this?
Thanks!
Edit: fixed table
You can create such a table as following:
CREATE TABLE laya2 (
id INT NOT NULL PRIMARY KEY,
f_name VARCHAR(20),
l_name VARCHAR(20),
supv_id INT,
INDEX supv_id_idx (supv_id),
FOREIGN KEY (supv_id)
REFERENCES laya2(id)
ON DELETE SET NULL -- example for an action
) ENGINE=INNODB;
My example sets the reference option to SET NULL, because I think it's the logical one here. If an employee who supervises others left, then those employees have no supervisor first. Another option would be to have NO ACTION because you could easily identify those employees without a valid supervisor and find a new supervisor for them. ON DELETE CASCADE would be wrong here, because those employees won't leave at the same time ...
You could insert employees with
INSERT INTO laya2 VALUES
(1, 'Han', 'Solo', NULL),
(2, 'Luke', 'Skywalker', 1);
(two successful inserts), but not with
INSERT INTO laya2 VALUES
(3, 'Anakin', 'Skywalker', 0);
This statement will fail because the foreign key constraint fails.
Deleting Han Solo will change the supv_id for Luke Skywalker to NULL, because of the reference option ON DELETE SET NULL
DELETE FROM laya2 WHERE id = 1; -- this will set the supv_id for Luke Skywalker to NULL
Yes, join the table to itself. Here's one of many ways:
SELECT a.l_name AS employee, b.l_name AS supervisor
FROM employee AS a, employee AS b
WHERE a.supv_id = b.id -- link tables
AND a.id = 2 -- get employee
Returns:
employee | supervisor
----------+-----------
Skywalker | Solo
Yes, you can define a foreign key that refers to the primary key of its own table.
create table employee (id int(10),
f_name varchar(10),
l_name varchar(10),
supv_id int(10)) ENGINE=InnoDB;
alter table employee add primary key (id);
alter table employee add foreign key (supv_id) references employee (id);
Employees without supervisor must have NULL in the supv_id column.

How to use foreign keys with PHP

So I understand how to create foreign keys and I know what is the purpose of the FK. But I have a problem in understanding How to use them. I asked a question regarding Foreign keys HERE(Click link)
Here is what I made:
CREATE TABLE user(
id INT(11) NOT NULL AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
password VARCHAR(20) NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE items(
i_id INT(11) NOT NULL AUTO_INCREMENT,
name TINYTEXT NOT NULL,
price DECIMAL(8,2) NOT NULL,
PRIMARY KEY (i_id)
);
CREATE TABLE user_purchase(
i_id INT(11) NOT NULL,
name TINYTEXT NOT NULL,
id INT(11) NOT NULL,
FOREIGN KEY (i_id) REFERENCES items(i_id),
FOREIGN KEY (name) REFERENCES items(name),
FOREIGN KEY (id) REFERENCES user(id)
);
Now my question is how do I make the most out of this using PHP? From the link above, people have suggested that it's good to use only one foreign key in the user_purchase table, but what if I want several columns? Why don't we use several foreign keys for different columns of the same table?
I am using mysql and php. I would appreciate it if you could show some examples of how you use PHP with the tables which have foreign keys to get get information using MYSQL commands. I really need a thorough explanation.
I also need to understand the terms Normalization and Denormalization. I would appreciate if you could give some links which explain these terms in great detail with examples or if you have any suggestion for some great books for beginners in database design, implementation, etc, I would really appreciate.
Thanks a lot.
Foreign key columns/constraints disambiguation
So I understand how to create foreign keys and I know what is the
purpose of the FK. But I have a problem in understanding How to use
them.
Assuming you are referring to the foreign key constraints, the short answer would be you just don't use them.
And here comes the long one:
We are accustomed to refer to columns being foreign keys to other tables. Especially during the normalization process, phrases like "user_purchase.i_id is a foreign key to the items table" would be very common. While that's a perfectly valid way to describe the relationship, it can get a little fuzzy when we reach the implementation phase.
Suppose you have created your tables without the FOREIGN KEY clauses:
CREATE TABLE user(
id INT(11) NOT NULL AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
password VARCHAR(20) NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE items(
i_id INT(11) NOT NULL AUTO_INCREMENT,
name TINYTEXT NOT NULL,
price DECIMAL(8,2) NOT NULL,
PRIMARY KEY (i_id)
);
CREATE TABLE user_purchase(
i_id INT(11) NOT NULL,
name TINYTEXT NOT NULL,
id INT(11) NOT NULL,
);
Notice that, relation-wise, the foreign key columns are still implemented. There's a column that references the user table (id) and another one that references the items table (i_id) -- let's put the name column aside for a moment. Consider the following data:
user user_purchase items
| id username | | id i_id | | i_id name price |
| 23 john | | 55 10 | | 10 chocolate bar 3.42 |
| 55 mary | | 70 10 | | 33 mobile phone 82.11 |
| 70 fred | | 70 33 | | 54 toothpaste 8.67 |
| 55 10 | | 26 toy car 6.00 |
| 70 26 |
The relation is there. It is implemented by means of the user_purchase table, which holds information as to who bought what. If we were to query the database for a relevant report, we would do:
select * from user_purchase p
join user u on (p.id=u.id)
join items i on (p.i_id=i.i_id)
And that's how we use the relation and the foreign key columns involved.
Now, what if we do:
insert into user_purchase (id,i_id) values (23,99)
Apparently, this is an invalid entry. Although there is a user with id=23, there's no item with i_id=99. The RDBMS would allow that to happen, because it doesn't know any better. Yet.
That's where foreign key constraints come into play. By specifying FOREIGN KEY (i_id) REFERENCES items(i_id) in the user_purchase table definition, we essentially give the RDBMS a rule to follow: entries with i_id values that are not contained in the items.i_id column are not acceptable. In other words, while a foreign key column implements the reference, a foreign key constraint enforces the referential integrity.
Note, however, that the above select wouldn't change, just because you defined a FK constraint. Thus, you don't use FK constraints, the RDBMS does, in order to protect your data.
Redundancies
...what if I want several columns? Why don't we use several foreign
keys for different columns of the same table?
Ask yourself: Why would you want that? If the two foreign keys are to serve the same purpose, the redundancy will eventually get you in trouble. Consider the following data:
user_purchase items
| id i_id name | | i_id name price |
| 55 10 chocolate bar | | 10 chocolate bar 3.42 |
| 70 10 chocolate bar | | 33 mobile phone 82.11 |
| 70 33 mobile phone | | 54 toothpaste 8.67 |
| 55 10 toothpaste | | 26 toy car 6.00 |
| 70 26 toy car |
What's wrong with this picture? Did user 55 buy two chocolate bars, or a chocolate bar and a toothpaste? This kind of ambiguity can lead to a lot of effort to keep data in-sync, which would be unnecessary if we just kept one of the foreign keys. In fact, why not drop the name column altogether, since it is implied by the relation.
Of course, we could resolve this by implementing a composite foreign key, by setting PRIMARY KEY(i_id,name) for the items table (or defining an extra UNIQUE(i_id,name) index, it doesn't realy matter) and then setting a FOREIGN KEY(i_id,name) REFERENCES items(i_id,name). This way, only (i_id,name) couples that exist in the items table would be valid for user_purchases. Apart from the fact that you would still have one foreign key, this approach is totally unnecessary, provided that the i_id column is already enough to identify an item (can't say the same for the name column...).
However, there's no rule against using multiple foreign keys to a table. In fact, there are circumstances that demand such an approach. Consider a person(id,name) table and a parent(person,father,mother) one, with the following data:
person parent
| id name | | person father mother |
| 14 John | | 21 14 59 |
| 43 Jane | | 14 76 43 |
| 21 Mike |
| 76 Frank |
| 59 Mary |
Obviously, all three columns of the parent table are foreign keys to person. Not for the same relation, though, but for three different ones: Since a person's parents are persons too, the two corresponding columns must reference the same table person does. Note, however, that the three fields not only can but also have to refer different persons in the same parent row, since noone is his own parent and noone's father is his mother as well.
Foreign keys are used in joins. For instance, if you want to know the usernames that purchased a particular item, you would write:
select u.username
from items i
join user_purchase up on i.i_id = up.i_id
join user u on u.id = up.id
where i.name = "Some product name"
They may also be used by the database engine itself. It can detect if you create a row in user_purchase whose id or i_id column doesn't match anything in the referenced column in the other table.
You should not replicate the name column in the user_purchase table. The name is just an attribute of the item, it's not specific to any particular purchase. If you need to get the name of the item that was purchased, join with the items table.
Instead of reading so many links, just try to implement this in any simple project. I'm just explaining how we gonna use the above tables.
Suppose you 3 users in user table and 5 items in items table.
user table
id | username | password
1 abc 123
2 def 456
3 qwe 987
items table
i_id | name | price
1 item 1 6
2 item 2 8
3 item 3 11
4 item 4 3
5 item 5 14
your user_purchase table look like this
CREATE TABLE user_purchase(
i_id INT(11) NOT NULL,
id INT(11) NOT NULL,
FOREIGN KEY (i_id) REFERENCES items(i_id),
FOREIGN KEY (id) REFERENCES user(id)
);
There is no need of item name again in this table. So I have removed.
i_id | id
1 1
1 2
2 2
3 3
In the above table we will get, user 1 has purchased item 1, user 2 has purchased item 1,item 2 and user 3 has purchased item 3.
This is how normalization works. You can use MySQL JOIN for getting user name and item details
SELECT B.user_name,C.name AS item_name,C.price
FROM user_purchase A
JOIN user B ON A.id = B.id
JOIN items C ON A.i_id = C.i_id
Here is foreign key use to join
A.id = B.id
A.i_id = C.i_id
You treet tables with foreign keys in php the same way, as if they had no foreign keys. Foreign keys are defined in the database and have (almost) nothing to do with php. The only thing you have to do in php is reacting to potential errors that can be returned by sql queries, which brake the foreign key constraint (typically DELETE queries).
And for your database schema, you should drop column "name" from "table user_purchase". It is redundat.
Just looking at the normalization/de-normalization point:
Normalization is a process of trying to remove redundancy in your database - in your example the name field in user_purchase is redundant - I can find out the name of the item by looking it up in the items table using i_id.
So if we were to look at normalizing user_purchase we'd probably remove the name field and use a JOIN to retrieve that when we needed it. This would, of course, also mean we don't need the second FOREIGN KEY reference to items.
De-normalization is basically going the opposite way - adding redundancy - usually done for performance reasons.
However, in your example you might also consider de-normalization for business reasons too. For example you might decide it is important to store the product name as it was when the user actually purchased it (rather than what it's called now) - just in case you need to be able to re-print an invoice for example. However even in this case you wouldn't want the FOREIGN KEY back to items (as it would "break" if the product was re-named).

How come I can enter values freely with foreign key constraint

I created two tables and did the following:
Table 1: (students)
CREATE TABLE student(s int, n int, d int, PRIMARY KEY(s), FOREIGN KEY(d) REFERENCES dep(d));
Table 2: (dep)
CREATE TABLE dep(d int, n int, PRIMARY KEY(d));
So, if i understand correctly, d is a foreign key of table 1 and it references to the primary key of the department. Therefore, The primary key of dep have to match the d in students. However when I do the following
INSERT INTO dep (1,2);
The statement finished with no error? The students table is empty, how could the data be inserted when its primary key is referenced?
Please help, thanks.
By the way I was able to insert into student freely even dep does not have corresponding value. Do you guys think it's because of mysql vs. oracle?
mysql> select * from student;
+---+------+------+
| s | n | d |
+---+------+------+
| 5 | 5 | 5 |
+---+------+------+
1 row in set (0.00 sec)
mysql> select * from dep;
+---+------+
| d | n |
+---+------+
| 1 | 2 |
+---+------+
1 row in set (0.00 sec)
The student table has the foreign key d which is the primary key of the dep table. The student table is the one dependent on the dep table. The dep table has no such dependence on the student table. The constraint is on the student table to have a value of d that should always be in dep table.
Inserting a record into the student table with an invalid value for d WILL cause the error.
You've got your understanding the wrong way round. What you've done in your sql is ensure that when you enter a Student, the value for d must exist as a value in dep.d
if you said
insert into student values (1, 2, 3)
then this would fail if there was no row in dep with d equal to 3
You can insert into the department table as there is no constraint on this table.
If you will try to add a row in student table with the random department number , which is not present in the department table, then it will give you the constraint error.
Example :If you will try
insert into student values (1, 4, 1034);
And if there is no row in the department table with the value of primary key 1034 , then it will give the foreign key constraint.
What you need to do is insert your data starting from the parent down.
If you need to delete data you actually have to go the other way, delete the items before you delete the parent order record.
As usual, when you insert data into the detail table and master table has no corresponding values, you got an error - 'Cannot add or update a child row: a foreign key constraint fails...'.
But when the FOREIGN_KEY_CHECKS variable is set to 0, MySQL ignores foreign key constraints -
SET FOREIGN_KEY_CHECKS=0;
INSERT INTO student VALUES (5,5,5); -- no errors
SET FOREIGN_KEY_CHECKS=1;