MySQL multiple fields foreign key referencing to single field - mysql

I have languages table which looks like that:
-id
-name
-iso
and in multiple tables I need to reference this iso field as foreign key. The problem is, I can't do it even if I give completely unique FK names. What is problem?
Here is how my Languages table contructed:
CREATE TABLE `Languages` (
`id` tinyint(3) unsigned NOT NULL AUTO_INCREMENT,
`iso` char(2) NOT NULL,
`name` varchar(255) NOT NULL,
`description` varchar(255) NOT NULL,
`order` tinyint(3) NOT NULL DEFAULT '0',
`active` tinyint(1) NOT NULL DEFAULT '1',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

Ensure that you have the same column datatype in your parent and child tables. Also create an index on your parent table's iso column. In absence of details in your question about tables you currently have and SQL you used for them, let's take some examples that you can compare with your database.
Example of different datatype:
create table languages (
id int,
name varchar(100),
iso char(3),
primary key(id)
);
create index ix_countries_iso on languages(iso);
create table countries (
id int,
iso int,
foreign key(iso) references languages(iso)
);
ERROR 1215 (HY000): Cannot add foreign key constraint
Example of missing index on parent table:
create table languages (
id int,
name varchar(100),
iso char(3),
primary key(id)
);
-- notice that we aren't creating an index on iso
create table countries (
id int,
iso char(3), -- notice correct datatype in child and parent table
foreign key(iso) references languages(iso)
);
ERROR 1215 (HY000): Cannot add foreign key constraint
What if you have the same datatype in parent and child but lengths are different? I'd recommend keeping the datatype and the length same but the following statements will work:
create table languages (
id int,
name varchar(100),
iso char(3),
primary key(id)
);
create index ix_countries_iso on languages(iso);
create table countries (
id int,
iso char(10), -- will work, but don't do this
foreign key(iso) references languages(iso)
);
create table countries2 (
id int,
iso char(1), -- will work also, but don't do this
foreign key(iso) references languages(iso)
);
Let's take an example of a working solution of foreign keys that you can compare with your database structure:
create table languages (
id int,
name varchar(100),
iso char(3),
primary key(id)
);
create index ix_countries_iso on languages(iso);
create table countries (
id int,
iso char(3), -- same datatype
foreign key fq_countries_languages(iso) references languages(iso)
);
create table boundaries (
id int,
iso char(3), -- same datatype
foreign key fq_boundaries_languages(iso) references languages(iso)
);
I'd also recommend that your child tables that rely on foreign key should be indexed also. Check out a nice little article on foreign keys.

Related

Can't create table `db`.`WRITER` (errno: 150 "Foreign key constraint is incorrectly formed")

Hello I have an issue when trying inserting multiple foreign keys to a table. I have searched a lot of hours and still I don't figure it out.. It pops this error. I don't know what else I can do about that. Also I tried to add constraint .. foreign key ... references command and it didn't work.
DROP DATABASE IF EXISTS db;
CREATE DATABASE db;
USE db;
CREATE TABLE BOOKS(
Bno int not null primary key auto_increment,
Title text,
PDate date,
Cno int,
Cname text
);
CREATE TABLE AUTHORS(
Ano int not null primary key auto_increment,
Asurname text,
Aname text
);
CREATE TABLE CATEGORIES(
Cno int not null primary key auto_increment,
Cname text,
No_Of_Books int
);
CREATE TABLE SUMMARY_LANG(
Bno int not null primary key auto_increment,
Language text,
FOREIGN KEY (Bno) REFERENCES BOOKS(Bno)
);
CREATE TABLE WRITER(
Bno int,
Ano int,
Asurname text,
Aname text,
FOREIGN KEY (Bno) REFERENCES BOOKS(Bno),
FOREIGN KEY (Ano) REFERENCES AUTHORS(Ano),
FOREIGN KEY (Asurname) REFERENCES AUTHORS(Asurname),
FOREIGN KEY (Aname) REFERENCES AUTHORS(Aname)
);
INSERT INTO BOOKS(Title,PDate,Cname)
VALUES
('A first course in database systems','2014-01-01','DATABASE'),
('FUNDAMENTAL CONCEPTS OF PROGRAMMING SYSTEMS','1976-01-01','PROGRAMMING');
ALTER TABLE AUTHORS auto_increment = 100;
INSERT INTO AUTHORS(Asurname,Aname)
VALUES
('ULLMAN','JEFF'),
('WIDOM','JENNIFER');
ALTER TABLE CATEGORIES auto_increment = 10;
INSERT INTO CATEGORIES(Cname, No_Of_Books)
VALUES
('DATABASE',1),
('PROGRAMMING',1);
INSERT INTO SUMMARY_LANG(Language)
VALUES
('ENG'),
('GRE'),
('ENG'),
('FRA');
Your definition of SUMMARY_LANG is wrong
CREATE TABLE SUMMARY_LANG(
Bno int not null primary key auto_increment,
Language text,
FOREIGN KEY (Bno) REFERENCES BOOKS(Bno) <-- remove this reference
);
Remove the foreign key, because this is a Table that is used only as reference number to another table also called a helper table, because the text would be redundant in the referenced table.
But i can't see any column that references language.
So add a column to BOOKS, where you add the reference to SUMMARY_LANG and when you add new rows SUMMARY_LANG you won't get any errors anymore.
So the new tables can be like this
CREATE TABLE BOOKS (
Bno INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
Title TEXT,
PDate DATE,
Cno INT,
Cname TEXT,
SNno int,
FOREIGN KEY (SNno)
REFERENCES SUMMARY_LANG (SNno)
);
CREATE TABLE SUMMARY_LANG(
SNno int not null primary key auto_increment,
Language text
);

MySQL - Update cell value using foreign key

I've got a problem creating a database.
I'd like to update children table using it's foreign key referencing to mother table automatically.
It means that when data values are inserted into the mother table, the children table gets updated on the column that is the foreign key.
Here's the code i wrote:
drop database domowa_biblioteka;
create database domowa_biblioteka;
use domowa_biblioteka;
create table pozycje
(
lp_p mediumint NOT NULL auto_increment,
nazwisko_autora char(30),
tytul char(60),
ilosc_stron int(4),
cena_oryginalna int(4),
na_sprzedaz enum('NIE','TAK'),
sprzedana enum('NIE','TAK'),
nr_pokoju mediumint,
PRIMARY KEY (lp_p)
)
;
create table kod_miedzynarodowy
(
lp_km mediumint,
ISBN char(20),
FOREIGN KEY (lp_km) REFERENCES pozycje (lp_p)
ON UPDATE CASCADE
)
;
create table pokoje
(
nr_pokoju mediumint NOT NULL auto_increment,
opis char(30),
PRIMARY KEY (nr_pokoju)
)
;
alter table pozycje ADD FOREIGN KEY (nr_pokoju) REFERENCES pokoje (nr_pokoju);
The thing is that the values of columns remain NULL after inserting data to rows.
Thanks for help!

How to reference a entity twice in the same table but with different variables?

I really hope I have used the right vocabulary, since I usually don't do this in English.
My problem is the following: I want to create a table that references to the same entity in another table twice, but with different variables.
In detail, I want to create a table called "matches" that references twice to the entity "name" in a table called "club", since a sports match obviously has two teams participating. This is what I tried to do:
CREATE TABLE aclub (
clubname varchar(100),
stadium varchar(100),
foundingdate integer,
PRIMARY KEY (clubname, stadium) ) ;
CREATE TABLE amatches (
matchnr integer PRIMARY KEY,
place varchar(100) REFERENCES aclub(stadium),
clubname1 varchar(100) REFERENCES aclub(clubname),
clubname2 varchar(100) REFERENCES aclub(clubname) ) ;
The error I get is the following:
ERROR: there is no unique constraint matching given keys for referenced table "aclub"
CREATE TABLE aclub (
id INT AUTO_INCREMENT PRIMARY KEY,
clubname varchar(100),
stadium varchar(100),
foundingdate integer,
UNIQUE (clubname),
UNIQUE (stadium)
) ;
CREATE TABLE amatches (
matchnr INTEGER AUTO_INCREMENT PRIMARY KEY,
club1 INTEGER REFERENCES aclub(id),
club2 INTEGER REFERENCES aclub(id),
place INTEGER REFERENCES aclub(id)
) ;
So you are have three references to the aclub table as in your question. But now we are using integers instead of varchar and that reduces redundancy
Use synthetic primary keys. This really makes it easier to design and use the data model:
CREATE TABLE aclub (
aclubId int auto_increment PRIMARY KEY,
clubname varchar(100),
stadium varchar(100),
foundingdate integer,
UNIQUE (clubname, stadium)
) ;
CREATE TABLE amatches (
matchnr integer auto_increment PRIMARY KEY,
aclubid integer,
foreign key (aclubid) references aclub(aclubid)
) ;
Your specific problem is that all the columns in a primary key need to be included in the foreign key definition. But why bother? Just use an auto-incremented id for the key and look up the information you want for the other fields.

MYSQL in PHPMYADMIN - create table relationship from one table

I want to create a table relationship with MYSQL PHPMYADMIN.
I have this Create table:
CREATE TABLE students(code_students int(8)not null AUTO_INCREMENT,
name_students varchar(25),
age_students int(3),
degree_program varchar(25),
code_advisor int(8)not null,
primary key(code_students, code_advisor)
);
and i want to make a create table named advise relationship between code_students, code_advisor.
Ok this is my tryout.
CREATE TABLE advise (
code_students int(8),
code_advisor int(8),
primary key(code_students, code_advisor),
foreign key(code_students)references students(code_students),
foreign key(code_advisor)references students(code_advisor)
);
mySQL says :
A FOREIGN KEY constraint that references a non-UNIQUE key is not standard SQL. It is an InnoDB extension to standard SQL
Try adding the UNIQUE keyword to your first table:
CREATE TABLE students(
code_students int(8)not null unique AUTO_INCREMENT,
name_students varchar(25),
age_students int(3),
degree_program varchar(25),
code_advisor int(8)not null unique,
primary key(code_students, code_advisor)
);
Check out this sqlFiddle and see how it works, then try removing the UNIQUE keywords and see that you get the same error that you mentioned. ( Hit the Build Schema button )
http://sqlfiddle.com/#!2/46b69

MySQL #1005 can't create table, but don't says why, errno:150

I'm making a database, with several tables, and so far I could make the tables, and update it with some demo data, but when a tried to make a new table for connecting two of my tables I just get this can't create table error whatever I did. Tried to rename the entities to an entirely different name maybe that's the problem but it wasn't.
CREATE DATABASE IF NOT EXISTS ETR;
CREATE TABLE Hallgato (
OktAzonosito INT(6) PRIMARY KEY,
EHAazonosito VARCHAR(11),
TeljesNev VARCHAR(50),
Szemelyazonosito INT(6),
AnyaNyelv VARCHAR(20),
VegzettsegSzint VARCHAR(25),
AnyjaNeve VARCHAR(35),
SzuletesiHely VARCHAR(30),
SzuletesiEv DATE,
Allampolgarsag VARCHAR(30),
Neme VARCHAR(5),
Adoazonosito INT(6),
TAJszam INT(6),
BankszamlaSzam INT(9)
) ENGINE = InnoDB;
CREATE TABLE OktAdat (
OktAzonosito INT(6),
NyelvVizsgaNyelve VARCHAR(15),
NyVegzesDatuma DATE,
NyIntezmeny VARCHAR(35),
EgyebVegzetteseg VARCHAR(15),
EgyVegzesDatuma DATE,
ID INT(5) PRIMARY KEY NOT NULL auto_increment,
FOREIGN KEY (OktAzonosito) REFERENCES Hallgato(OktAzonosito) ON DELETE CASCADE
) ENGINE = InnoDB;
CREATE TABLE Oktato (
TEHAazonosito VARCHAR(11) PRIMARY KEY,
Nev VARCHAR(50),
SzuletesiEv DATE,
Szakterulet VARCHAR(25),
Telefonszam INT(9),
Email VARCHAR(50)
) ENGINE = InnoDB;
CREATE TABLE Kurzus (
KurzusKod VARCHAR(8) PRIMARY KEY,
KurzusNev VARCHAR(30),
Idotartam INT(3),
EloadasHelye VARCHAR(25),
Tipus CHAR(3),
Vizsgatipus VARCHAR(7),
KreditErtek INT(2),
OktatoKod VARCHAR(11)
) ENGINE = InnoDB;
CREATE TABLE Terem (
Sorszam INT(3) PRIMARY KEY NOT NULL,
Epuletszam INT(1),
Kapacitas INT(3),
IRszam INT(4),
Utca CHAR(25),
Hazszam INT(2)
) ENGINE = InnoDB;
CREATE TABLE DiakKurz (
kd_id INT (5) PRIMARY KEY NOT NULL auto_increment,
DKKod VARCHAR(8),
EHA VARCHAR(11),
FOREIGN KEY (EHA) REFERENCES Hallgato(EHAazonosito) ON DELETE CASCADE,
FOREIGN KEY (DKKod) REFERENCES Kurzus(KurzusKod) ON DELETE CASCADE
) ENGINE = InnoDB;
The problem is with creating the DiakKurz table.
You'll have to set an INDEX for column EHAazonosito in table Hallgato
CREATE TABLE Hallgato (
OktAzonosito INT(6) PRIMARY KEY,
EHAazonosito VARCHAR(11), INDEX (EHAazonosito),
TeljesNev VARCHAR(50),
Szemelyazonosito INT(6),
AnyaNyelv VARCHAR(20),
VegzettsegSzint VARCHAR(25),
AnyjaNeve VARCHAR(35),
SzuletesiHely VARCHAR(30),
SzuletesiEv DATE,
Allampolgarsag VARCHAR(30),
Neme VARCHAR(5),
Adoazonosito INT(6),
TAJszam INT(6),
BankszamlaSzam INT(9)
) ENGINE = InnoDB;
This
FOREIGN KEY (EHA) REFERENCES Hallgato(EHAazonosito) ON DELETE CASCADE,
doesn't work because EHAazonosito is not the primary key of the Hallgato table. A foreign key can only reference a primary (or unique) key.
Btw: are you awary that the 6 in int(6) is not about limiting the values in the column?
It doesn't do anything. int(6) is the same as int. The 6 is only there to give client applications a hint(!) with how many digits the column should be displayed. It does not enforce anything at all.
Have you tried looking up the error?
If MySQL reports an error number 1005 from a CREATE TABLE statement,
and the error message refers to error 150, table creation failed
because a foreign key constraint was not correctly formed. Similarly,
if an ALTER TABLE fails and it refers to error 150, that means a
foreign key definition would be incorrectly formed for the altered
table. To display a detailed explanation of the most recent InnoDB
foreign key error in the server, issue SHOW ENGINE INNODB STATUS.
http://dev.mysql.com/doc/refman/5.5/en/innodb-foreign-key-constraints.html
it happened also to me after a dump of the whole schema, what helped was to wrap whole dump within disabled foreign key checks
SET foreign_key_checks=0;
...dump
SET foreign_key_checks=1;