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;
Related
I have the following table:
questions_answers
_____________________________________
| id | question_id | answer | user_id |
|____|_____________|________|_________|
| 1 | 1 | yes | 3 |
|____|_____________|________|_________|
I want to check if question_id and user_id exist, Then update the existing row.
I tried this command INSERT INTO questions_answers (question_id, answer, user_id) VALUES (1, 'no',3) ON DUPLICATE KEY UPDATE answer = 'no'
So in this case there is a question_id = 1 and user_id = 3, Hence it should update that row and not insert a new row.
But I think it checks the id column for dublicates.
Is there is a way to get this done with SQL or I need to check if row exists with PHP, then update?
Your INSERT INTO .. ON DUPLICATE KEY UPDATE is not working because the current KEY that determine the duplication/violation is the id column primary key.
From the spec of this syntax
INSERT ... ON DUPLICATE KEY UPDATE is a MariaDB/MySQL extension to the INSERT statement that, if it finds a duplicate unique or primary key, will instead perform an UPDATE.
To achieve this, you will need to create a UNIQUE CONSTRAINT on two columns question_id and user_id. This unique constraint will raise upon the duplication of question_id - user_id pair, and triggers the UPDATE statement as you intends.
ALTER TABLE questions_answers ADD CONSTRAINT uq_user_question UNIQUE KEY(question_id ,user_id);
Reference:
MySQL Insert On Duplicate
MariaDB - INSERT ON DUPLICATE KEY UPDATE
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.
I think this is a common problem but I was not able to find correct keywords to perform a search on StackOverflow.
In mysql, I have two entites : organization and scale.
One organization can only have one scale but a scale can belong to many organizations.
So I created a third entity organization_scale.
for instance :
organization
------------
org_id | name
1 | Mickey
2 | Donald
3 | Dingo
scale
----------
sc_id | name
1 | miniScale
2 | maxiScale
organization_scale
--------------
org_id | sc_id
1 | 1
2 | 1
3 | 2
Both fields of the organization_scale entity are foreign keys + cascade on update and delete
The problem is the following:
If I delete from organization where org_id = 3,the third line from organization_scale are properly deleted (since org_id = 3 does not exist anymore)
BUT
the scale with sc_id = 2 is not deleted. And I do not understand why. No one references to this scale, and this should be removed otherwise, with a big amount of data, a lot of "scales" will be orphean.
(same thing happens if I do not use an extra table, and I add a scale_id column directly in organization)
I think the problem is this: The ON DELTE CASCADE in the definition of the organization_scale table only works in one direction: when deleting something in scale or organization then don't ask and delete the rows in organization_scale.
But you seem to want the other direction: When deleting something in organization_scale delete the row in scale if there is no reference to it anymore.
This works for me: I added a trigger on organization.
DROP DATABASE IF EXISTS test;
CREATE DATABASE test;
USE test;
CREATE TABLE organization (org_id INT UNSIGNED PRIMARY KEY, name VARCHAR(255));
CREATE TABLE scale (sc_id INT UNSIGNED PRIMARY KEY, name VARCHAR(255));
CREATE TABLE organization_scale (org_id INT UNSIGNED, sc_id INT UNSIGNED,
FOREIGN KEY (org_id)
REFERENCES organization(org_id)
ON UPDATE CASCADE ON DELETE CASCADE,
FOREIGN KEY (sc_id)
REFERENCES scale(sc_id)
ON UPDATE CASCADE ON DELETE CASCADE
);
CREATE TRIGGER delete_unused_sc_id AFTER DELETE ON organization FOR EACH ROW DELETE FROM scale WHERE NOT EXISTS (SELECT * FROM organization_scale WHERE organization_scale.sc_id = scale.sc_id);
INSERT INTO organization VALUES
(1,"Mickey"),
(2,"Donald"),
(3,"Dingo");
INSERT INTO scale VALUES
(1,"miniScale"),
(2,"maxiScale");
INSERT INTO organization_scale VALUES
(1,1),
(2,1),
(3,2);
SELECT * FROM organization_scale;
SELECT * FROM scale;
DELETE FROM organization WHERE org_id=3;
SELECT * FROM organization_scale;
SELECT * FROM scale;
DROP DATABASE test;
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.
I am a noob in MySql. I want to create the following self-referencing table:
EMPLOYEE
+-----+------+------+
|Name |E-ID |M-ID |
+-----+------+------+
|ABC |12345 |67890 |
|DEF |67890 |12345 |
+-----+------+------+
I use the following commands:
CREATE TABLE EMPLOYEE (
NAME VARCHAR(20) ,
E-ID CHAR(6) NOT NULL ,
M-ID CHAR(6) NULL ,
PRIMARY KEY (E-ID) ,
FOREIGN KEY (M-ID) REFERENCES EMPLOYEE(E-ID)
);
Now my problem is, how do I enter the two records? I mean, each time the foreign constraint will fail. I tried entering:
INSERT INTO EMPLOYEE VALUES('12345','67890');
I also tried :
INSERT INTO EMPLOYEE VALUES('12345','67890'),('67890','12345');
Both of the above commands fail. Giving error:
ERROR 1452 (23000): Cannot add or update a child row: a foreign key
constraint fails BLAH BLAH
Guys, actually I was trying to implement the tables given in slide number 25 of the following ppt: The Relational Data Model and Relational Database Constraints
The constraints are:
SUPERSSN Of EMPLOYEE references SSN of EMPLOYEE.
MGRSSN of DEPARTMENT references SSN of EMPLOYEE.
DNO of EMPLOYEEE references DNumber of DEPARTMENT.
After I have created the tables, how do I add records? It will always fail the foreign key constraints.
As MySQL does not support deferrable constraints (which are the "natural solution" to such a problem) you will need to do this in two steps;
INSERT INTO employee (name, `E-ID`) values ('Arthur', '123456');
INSERT INTO employee (name, `E-ID`) values ('Ford', '67890');
UPDATE employee
SET `M-ID` = '67890'
WHERE `E-ID` = '123456';
UPDATE employee
SET `M-ID` = '123456'
WHERE `E-ID` = '67890';
You circular reference does sound strange to me though. An employee being the manager of an employee who is in turn his manager?
Allow me two comments on your table definition:
avoid column (or table names) with special characters that need quoted identifiers. Using E_ID instead of E-ID will save you some trouble in the long run
If your employee ID can be shorter than 6 characters than you most probably want to use VARCHAR(6) instead of CHAR(6) due to the padding of the values with the CHAR datatype.
There are good answers here, but figured I'd point out the quick-and-dirty:
SET FOREIGN_KEY_CHECKS = 0;
INSERT INTO EMPLOYEE VALUES('12345','67890'),('67890','12345');
SET FOREIGN_KEY_CHECKS = 1;
It will obviously fail because the table is empty.
INSERT INTO EMPLOYEE VALUES('12345','67890');
Since M-ID depends on E-ID. Remove the constraint so you can insert record. The best thing you do is to create another table for M-ID and reference it to Employee table.