Can't add foreign key to mysql - mysql

I have multiple tables and they all seem to be fine but there is this one table which I'm trying to create but it wont work because I am keep on getting Error1005 "Foreign key constraint is incorrectly formed".
These are the two tables. I don't know what seems to be the problem.
CREATE TABLE Patient(
ID INT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE,
Name VARCHAR(255) NOT NULL,
Age TINYINT UNSIGNED,
Sex VARCHAR(10),
Contact INT(11),
Email TEXT(2083),
PRIMARY KEY(ID)
);
CREATE TABLE Appointments (
Appointment_No INT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE,
Name VARCHAR(255) NOT NULL,
Contact INT(11),
Date DATE NOT NULL,
Time TIME NOT NULL,
Reason TEXT(2083),
PRIMARY KEY(Appointment_No),
FOREIGN KEY (Name, Contact) REFERENCES Patient (Name, Contact)
);

As per me, table structure should be like below:
CREATE TABLE Patient(
ID INT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE,
Name VARCHAR(255) NOT NULL,
Age TINYINT UNSIGNED,
Sex VARCHAR(10),
Contact INT(11),
Email TEXT(2083),
PRIMARY KEY(ID)
);
CREATE TABLE Appointments (
Appointment_No INT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE,
Patient_ID INT UNSIGNED NOT NULL,
Date DATE NOT NULL,
Time TIME NOT NULL,
Reason TEXT(2083),
PRIMARY KEY(Appointment_No),
FOREIGN KEY (Patient_ID) REFERENCES Patient (ID)
);

FOREIGN KEY (Name, Contact) REFERENCES Patient (Name, Contact)
The referenced columns in the Patient table must be part of a key. Ideally you would want Patient (Name, Contact) to be a unique key, because then the foreign key is guaranteed to reference exactly one row in the Patient table.
But in your table definition, the Name and Contact columns are not part of a key. That explains why you got the error given your table design.
But your table design is not good. Name and Contact are not good choices as a unique key, because two people can share a name, and in theory you could even have two people with the same name with the same contact details (for example, the former boxer George Foreman named his five sons George).
#Shadow is correct that it's a better idea is to reference Patient(id) instead, because it's guaranteed to be unique already.

Define Engine so sql statement would end with
ENGINE = MyISAM;
It should fix the issue.

Try to split the two foreign keys in two lines like this:
FOREIGN KEY (Contact) REFERENCES Patient (Contact)
FOREIGN KEY (Name) REFERENCES Patient (Name)

Related

passing multiple foregain values in sql cell

I have two tables tb_schools(school_id,school_name), tb_programms(pid,p_name,school_id)
If suppose multiple schools offer the same program then how can I design the DB.
I mean can I pass the list of school_ids like[sc1,sc2,sc3] in school_id of tb_programms.
note: I can't add multiple rows for a single program.
If multiple schools offer the same program you need to design your schema differently. The canonical solution would be to have a table for schools, a table for programs, and a mapping table for the programs held at each school. E.g.:
CREATE TABLE tb_schools (
school_id INT AUTO_INCREMENT PRIMARY KEY,
school_name VARCHAR(30) NOT NULL
);
CREATE TABLE tb_programs (
pid INT AUTO_INCREMENT PRIMARY KEY,
p_name VARCHAR(30) NOT NULL
);
CREATE TABLE tb_school_programs
sid INT NOT NULL,
pid INT NOT NULL,
PRIMARY KEY (sid, pid),
FOREIGN KEY (sid) REFERENCES school(school_id),
FOREIGN KEY (pid) REFERENCES programs(pid)
);

is naming the unique constraint with multiple columns significant?

Suppose i have a table customers having multiple fields. I am considering, three fields to be unique :date of birth, phone number, mail id. in order to create this table, the create script would be:
create table customers(
customer_id INT AUTO_INCREMENT,
first_name VARCHAR(255),
last_name VARCHAR(255),
address VARCHAR(255),
DOB datetime Not NULL,
phone_number int(10) NOT NULL,
email_address VARCHAR(255) NOT NULL,
PRIMARY KEY (customer_id),
UNIQUE KEY (customer_id,DOB,phone_number,email_address)
);
however i have noticed that unique key is declared with a name - UNIQUE KEY customer_id (customer_id,DOB,phone_number,email_address).
I need help in understanding why and when the unique constraint to be named, and what value would it add? Also what is the best practice for naming?
(Note:I do understand the concept of UNIQUE INDEX, but here i want to understand the naming of UNIQUE constraint)

Which database scheme is better for performance aspect?

----Scheme1----
CREATE TABLE college (
id INT AUTO_INCREMENT,
name VARCHAR(250) NOT NULL,
address VARCHAR(250),
PRIMARY KEY (id)
);
CREATE TABLE student (
college INT NOT NULL,
username VARCHAR(50) NOT NULL,
name VARCHAR(100),
FOREIGN KEY (college) REFERENCES college(id),
CONSTRAINT pk PRIMARY KEY (college,username)
);
CREATE TABLE subject (
college INT NOT NULL,
id INT NOT NULL,
name VARCHAR(100),
FOREIGN KEY (college) REFERENCES college(id),
CONSTRAINT pk PRIMARY KEY (college,id)
);
CREATE TABLE marks (
college INT NOT NULL,
student VARCHAR(50) NOT NULL,
subject INT NOT NULL,
marks INT NOT NULL,
// forget about standard for this example
FOREIGN KEY (college) REFERENCES college(id),
FOREIGN KEY (student) REFERENCES student(username),
FOREIGN KEY (subject) REFERENCES subject(id),
CONSTRAINT pk PRIMARY KEY (college,subject,student)
);
----Scheme2----
CREATE TABLE college (
id INT AUTO_INCREMENT,
name VARCHAR(250) NOT NULL,
address VARCHAR(250),
PRIMARY KEY (id)
);
CREATE TABLE student (
college INT NOT NULL,
id BIGINT NOT NULL AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
name VARCHAR(100),
FOREIGN KEY (college) REFERENCES college(id),
PRIMARY KEY (id)
);
CREATE TABLE subject (
college INT NOT NULL,
id BIGINT NOT NULL AUTO_INCREMENT,
name VARCHAR(100),
FOREIGN KEY (college) REFERENCES college(id),
PRIMARY KEY (id)
);
CREATE TABLE marks (
student VARCHAR(50) NOT NULL,
subject INT NOT NULL,
id BIGINT NOT NULL AUTO_INCREMENT,
marks INT NOT NULL,
// forget about standard for this example
FOREIGN KEY (student) REFERENCES student(id),
FOREIGN KEY (subject) REFERENCES subject(id),
PRIMARY KEY (id)
);
Looking at the above database schemes it looks like Scheme1 will give better performance while searching for the result of a specific student and faster in filtering results but it feels like it is not in all normalized forms. While Scheme2, on the other hand, looks to be fully normal but might require more JOIN operations to fetch certain results or filter the data.
Please tell me if I'm wrong about my Schemes here, also tell me which one is better?
I would go for Schema 2: when it comes to reference a table, it is easier done by using a single column (auto_incremented primary key in Schema 1) than a combination of columns (coumpound primary keys in Schema 1). Also, as commented by O.Jones, Schema 2 assumes that two students in the same college cannot have the same name, which does not seem sensible.
There are other issues with Schema 1, eg the foreign key that relates the marks to students is malformed (you would need a coumpound foreign keys that include the college id instead of just the student name).
With properly defined foreign keys referencing primary keys, performance will not be a problem; joins perform good in this situation.
But one flaw should be fixed in Schema 2, that is to store a reference to the college in the marks table. You don't need this, since a student belongs to a college (there is a reference to the college in the student table).
Also, I am unsure that a subject should belong to a college: isn't it possible that the same subject would be taught in different colleges?
Finally, I would suggest giving clearer names to the foreign key columns, like student_id instead of student, and college_id instead of college.
It's difficult to assess whether a schema is normalized without first knowing the the relationships between entities. Can a student be associated with only one college? Can a student be associated multiple times over with the same subject, getting different marks?
Declaring foreign keys maintains referential integrity but slows down insertions and updates. You can get the same functionality without declaring the fks, but you may end up with some orphaned records. The fact that a particular index is used for a fk, or not, makes no difference to SELECT query performance.
JOIN operations use indexes. So do fks. So if you have the correct indexes, your JOIN operations will be efficient. But it's impossible to know which indexes are the best without knowing your JOIN queries.
Conventionally, each table's id column comes first. And many designers name each id column after the table in which it appears, for example college.college_id rather than college.id. That makes JOIN queries slightly easier to read.
You should use a surrogate primary key in the student table (student.student_id) rather than using the student's name as part of the primary key. JOINing on id values is faster than joining on VARCHAR() values. And, some students may share names. (In the real world, peoples's dates of birth accompany their names in tables: it helps tell people apart.)
I think your marks table should contain these columns:
CREATE TABLE marks (
student_id INT NOT NULL,
subject_id INT NOT NULL,
marks INT NOT NULL,
// foreign keys as needed
PRIMARY KEY (student_id, subject_id)
);
Can a student have multiple marks for the same subject? In that case use a marks_id as the pk instead of (student_id, subject_id).

Simple attendance list SQL schema architecture advice

I have a sport club presence list on paper which I have to bring online.
Basically, I have everything in handle except the SQL schema architecture.
I have never designed a DataBase and I'm not sure if it's the right way. I appreciate any help!
If the person is present we make a x with a pen on paper :)
To do to look the same like on the paper but in an app I try to develop a Java Vaadin App with Spring Data JPA-Hibernate.
On paper and in the future APP look like this:
And this is the MySQL schema:
create table person(
id int PRIMARY KEY AUTO_INCREMENT,
first_name varchar(20)
);
create table isPresent(
id int PRIMARY KEY AUTO_INCREMENT,
isPresent boolean
);
create table persons_isPresent(
person_id int,
isPresent_id int,
FOREIGN KEY (person_id)
REFERENCES person(id),
FOREIGN KEY (isPresent_id)
REFERENCES isPresent(id)
);
create table training(
id int PRIMARY KEY AUTO_INCREMENT,
person_id int,
isPresent_id int,
training_time datetime,
FOREIGN KEY (person_id)
REFERENCES person(id),
FOREIGN KEY (isPresent_id)
REFERENCES isPresent(id)
);
I have never designed a DataBase and I'm not sure if it's the right way. I appreciate any help!
It seems unnecessary to have ispresent ID's.
I would keep your Person table as is.
Create a Training table with an ID and time, and an TrainingAttendance table with a Training ID and a Person ID. If you want to check a person's attendance at a training, check if a record exists in TrainingAttendance with the Person's ID and the Training ID.
CREATE TABLE PERSON (
PERSON_ID INTEGER NOT NULL PRIMARY KEY,
FIRST_NAME VARCHAR(20) NOT NULL);
CREATE TABLE TRAINING (
TRAINING_ID INTEGER NOT NULL PRIMARY KEY
TRAINING_TIME DATETIME NOT NULL);
CREATE TABLE TRAINING_ATTENDANCE (
TRAINING_ID INTEGER NOT NULL,
PERSON_ID INTEGER NOT NULL,
FOREIGN KEY(PERSON_ID) REFERENCES PERSON(PERSON_ID),
FOREIGN KEY(TRAINING_ID) REFERENCES TRAINING(TRAINING_ID),
PRIMARY KEY(TRAINING_ID, PERSON_ID));
I think it might be cleaner to think about training sessions independently. Then you could achieve that with three tables [training]<-[attendee]->[person], where the attendee is a binding table. So maybe something like this:
create table training(
id int PRIMARY KEY AUTO_INCREMENT,
training_time datetime
);
create table person(
id int PRIMARY KEY AUTO_INCREMENT,
first_name varchar(20)
);
create table attendee(
id int PRIMARY KEY AUTO_INCREMENT,
person_id int,
training_id int,
FOREIGN KEY (person_id) REFERENCES person(id),
FOREIGN KEY (training_id) REFERENCES training(id)
);
I tried it out with some simple inserts/select and it might do the trick for you?
insert INTO person (first_name) VALUES ('Pavel');
insert INTO training (training_time) VALUES (NOW());
insert INTO attendee (person_id, training_id) VALUES (1,1);
select person.first_name, training.training_time
from attendee, person, training
where person.id = attendee.person_id
AND training.id = attendee.training_id;

Can a table have two foreign keys?

I have the following tables (Primary key in bold. Foreign key in Italic)
Customer table
ID---Name---Balance---Account_Name---Account_Type
Account Category table
Account_Type----Balance
Customer Detail table
Account_Name---First_Name----Last_Name---Address
Can I have two foreign keys in the Customer table and how can I implement this in MySQL?
Updated
I am developing a web based accounting system for a final project.
Account Category
Account Type--------------Balance
Assets
Liabilities
Equity
Expenses
Income
Asset
Asset_ID-----Asset Name----Balance----Account Type
Receivable
Receivable_ID-----Receivable Name-------Address--------Tel-----Asset_ID----Account Type
Receivable Account
Transaction_ID----Description----Amount---
Balance----Receivable_ID----Asset_ID---Account Type
I drew the ER(Entity relationship) diagram using a software and when I specify the relationship it automatically added the multiple foreign keys as shown above. Is the design not sound enough?
create table Table1
(
id varchar(2),
name varchar(2),
PRIMARY KEY (id)
)
Create table Table1_Addr
(
addid varchar(2),
Address varchar(2),
PRIMARY KEY (addid)
)
Create table Table1_sal
(
salid varchar(2),`enter code here`
addid varchar(2),
id varchar(2),
PRIMARY KEY (salid),
index(addid),
index(id),
FOREIGN KEY (addid) REFERENCES Table1_Addr(addid),
FOREIGN KEY (id) REFERENCES Table1(id)
)
Yes, MySQL allows this. You can have multiple foreign keys on the same table.
Get more details here FOREIGN KEY Constraints
The foreign keys in your schema (on Account_Name and Account_Type) do not require any special treatment or syntax. Just declare two separate foreign keys on the Customer table. They certainly don't constitute a composite key in any meaningful sense of the word.
There are numerous other problems with this schema, but I'll just point out that it isn't generally a good idea to build a primary key out of multiple unique columns, or columns in which one is functionally dependent on another. It appears that at least one of these cases applies to the ID and Name columns in the Customer table. This allows you to create two rows with the same ID (different name), which I'm guessing you don't want to allow.
Yes, a table have one or many foreign keys and each foreign keys hava a different parent table.
CREATE TABLE User (
user_id INT NOT NULL AUTO_INCREMENT,
userName VARCHAR(100) NOT NULL,
password VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL,
userImage LONGBLOB NOT NULL,
Favorite VARCHAR(255) NOT NULL,
PRIMARY KEY (user_id)
);
and
CREATE TABLE Event (
EventID INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY (EventID),
EventName VARCHAR(100) NOT NULL,
EventLocation VARCHAR(100) NOT NULL,
EventPriceRange VARCHAR(100) NOT NULL,
EventDate Date NOT NULL,
EventTime Time NOT NULL,
EventDescription VARCHAR(255) NOT NULL,
EventCategory VARCHAR(255) NOT NULL,
EventImage LONGBLOB NOT NULL,
index(EventID),
FOREIGN KEY (EventID) REFERENCES User(user_id)
);