I have one question, so there are two tables:
CREATE TABLE Account (
id INT NOT NULL AUTO_INCREMENT,
user_id INT NOT NULL,
name VARCHAR(35) NOT NULL,
balance DOUBLE NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (user_id) REFERENCES User (id)
);
CREATE TABLE Operation (
id INT NOT NULL AUTO_INCREMENT,
source_id INT NOT NULL,
destination_id INT NULL,
operation_type VARCHAR(20) NOT NULL,
date DATE NOT NULL,
total DOUBLE NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (source_id) REFERENCES Account (id)
-- Wrong!!!
FOREIGN KEY (destination_id) REFERENCES Account (id)
);
Fields source_id and destination_id have to refer to Account table because each operation should have an account source and not required destination account.
If I have set up source_id as a foreign key in the Operation table that refers to the Account table. How can I make the correct relationship between destination_id and Account table?
I believe it should be in a third table, but I can't figure out how it could be organised in a proper way.
Related
Let's say I have a database of families, persons and dogs. Each family has 0 or more persons, each person has 0 or more dogs and no dogs in the same family may have the same name. Is it possible to declare a uniqueness constraint for dogs that "jumps" one table, i.e. something like
CREATE TABLE Family (
ID int NOT NULL,
LastName varchar(255) NOT NULL,
PRIMARY KEY (ID)
);
CREATE TABLE Person (
ID int NOT NULL,
FamilyID int NOT NULL,
FirstName varchar(255) NOT NULL,
PRIMARY KEY (ID),
FOREIGN KEY (FamilyID) REFERENCES (Family.ID)
);
CREATE TABLE Dog (
ID int NOT NULL,
PersonID int NOT NULL,
Name varchar(255) NOT NULL,
PRIMARY KEY (ID),
FOREIGN KEY (PersonID) REFERENCES (Person.ID),
UNIQUE (Name, Person.FamilyID)
);
? UNIQUE(Name, Person.FamilyID) obviously does not work, but it should make my intentions clear.
If not, (or perhaps even better, actually) is it possible to have something like
CREATE TABLE Family (
ID int NOT NULL,
LastName varchar(255) NOT NULL,
PRIMARY KEY (ID)
);
CREATE TABLE Person (
ID int NOT NULL,
FamilyID int NOT NULL,
FirstName varchar(255) NOT NULL,
PRIMARY KEY (ID),
FOREIGN KEY (FamilyID) REFERENCES (Family.ID)
);
CREATE TABLE Dog (
ID int NOT NULL,
FamilyID int NOT NULL,
PersonID int NOT NULL,
Name varchar(255) NOT NULL,
PRIMARY KEY (ID),
FOREIGN KEY (FamilyID) REFERENCES (Family.ID),
FOREIGN KEY (PersonID) REFERENCES (Person.ID),
UNIQUE (Name, FamilyID)
);
and enforce consistency between Dog.FamilyID and Dog.PersonID? That is, to ensure that the FamilyID is the same for the dog and the person?
Bonus points if a dog can belong to the entire family by , i.e. Dog.PersonID is nullable.
No, you cannot create UNIQUE constraints that span multiple tables (well... maybe in the exotic case of an oracle bitmap join index, but that's a different story).
The typical solution is to use composite keys. That way the column from the first table will be present in the second and third table, and it would be easy to enforce the uniqueness you want.
For example:
CREATE TABLE Family (
ID int NOT NULL,
LastName varchar(255) NOT NULL,
PRIMARY KEY (ID)
);
CREATE TABLE Person (
ID int NOT NULL,
FamilyID int NOT NULL,
FirstName varchar(255) NOT NULL,
PRIMARY KEY (ID),
UNIQUE (ID, FamilyID), -- unique composite constraint
FOREIGN KEY (FamilyID) REFERENCES Family (ID)
);
CREATE TABLE Dog (
ID int NOT NULL,
PersonID int NOT NULL,
FamilyID int NOT NULL,
Name varchar(255) NOT NULL,
PRIMARY KEY (ID),
FOREIGN KEY (PersonID, FamilyID) REFERENCES Person (ID, FamilyID),
UNIQUE (Name, FamilyID)
);
Forget it. Just attach the dog to a person. Then look up the family from the person.
Trying to managing redundant relationships across tables is just fraught with problems. It is quite easy to get the family looking up the person.
In other words, remove familyId from the dogs table.
this is my code:
CREATE DATABASE exams;
SHOW DATABASES;
CREATE TABLE IF NOT EXISTS students(
student_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
first_name VARCHAR(20) NOT NULL,
middle_name VARCHAR(40),
last_name VARCHAR(40)NOT NULL,
email VARCHAR(60) NOT NULL,
password CHAR(40) NOT NULL,
reg_date DATETIME NOT NULL,
PRIMARY KEY (student_id),
UNIQUE(email));
SHOW table status
INSERT INTO exams_3121(student_id, first_name, middle_name, last_name, email, password, reg_date)
CREATE TABLE entries
(
entrie_id int NOT NULL,
student_id int NOT NULL,
subject_id int,
PRIMARY KEY (entrie_id),
FOREIGN KEY (student_id) REFERENCES student(student_id),
FOREIGN KEY (subject_id)REFERENCES subject(subject_id)
)
CREATE DATABASE subjects;
CREATE TABLE IF NOT EXISTS subjects(
subject_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
subject_name VARCHAR(20) NOT NULL,
level_entery VARCHAR(40)NOT NULL,
exam_board VARCHAR(60) NOT NULL,
PRIMARY KEY (subject_id));
CREATE TABLE entries
(
entrie_id int NOT NULL,
entrie_id int NOT NULL,
subject_id int,
PRIMARY KEY (entrie_id),
FOREIGN KEY (student_id) REFERENCES student(student_id),
FOREIGN KEY (subject_id)REFERENCES subject(subject_id)
)
When I use this code it says cannot add foreign key constraint
and I don't know what to do. Please and thanks in advance.
There are two problems.
First, you got the names of the table you're referencing wrong. The name of the tables are students and subjects, but you wrote student and subject.
Second, the entries table has two entrie_id columns. One of them should be student_id.
CREATE TABLE entries
(
entrie_id int NOT NULL,
student_id int NOT NULL,
subject_id int,
PRIMARY KEY (entrie_id),
FOREIGN KEY (student_id) REFERENCES students(student_id),
FOREIGN KEY (subject_id) REFERENCES subjects(subject_id)
)
Also, if you're creating multiple databases and putting your tables in them, you'll need to refer to tables with their database prefixes if they're different from the one you selected as default with the USE command. As you've written it, you're not actually using the databases you created with CREATE DATABASE.
I am having trouble adding a customer and their order to an order table once they have checked out.
Here is my SQL for creating the four tables I am using:
CREATE TABLE IF NOT EXISTS Product(
ID int NOT NULL AUTO_INCREMENT,
Name varchar(255) NOT NULL,
Description text(65535) NOT NULL,
Quantity int NOT NULL,
Photo varchar(255),
Price float NOT NULL,
Category varchar(50),
PRIMARY KEY (ID)
) ENGINE=innoDB;
CREATE TABLE IF NOT EXISTS Customer(
ID int NOT NULL AUTO_INCREMENT,
FirstName varchar(255) NOT NULL,
LastName varchar(255) NOT NULL,
Email varchar(255) NOT NULL,
PhoneNumber varchar(11) NOT NULL,
Address varchar(50),
Town varchar(50),
County varchar(50),
PostCode varchar(50),
PRIMARY KEY (ID)
) ENGINE=innoDB;
CREATE TABLE IF NOT EXISTS OrderTable(
ID int NOT NULL AUTO_INCREMENT,
Date date NOT NULL,
PRIMARY KEY (ID),
TotalPrice float NOT NULL,
Customer_ID int NOT NULL,
CONSTRAINT fk_Order_1
FOREIGN KEY (Customer_ID)
REFERENCES coursework_db.Customer (ID)
) ENGINE=innoDB;
CREATE TABLE IF NOT EXISTS OrderItem(
ID int NOT NULL AUTO_INCREMENT,
PRIMARY KEY (ID),
Product_ID int NOT NULL,
Order_ID int NOT NULL,
Quantity int NOT NULL,
TotalPrice float NOT NULL,
CONSTRAINT fk_OrderItem_1
FOREIGN KEY (Product_ID)
REFERENCES coursework_db.Product(ID),
CONSTRAINT fk_OrderItem_2
FOREIGN KEY (Order_ID)
REFERENCES coursework_db.OrderTable(ID)
) ENGINE=innoDB;
The problem I am having is how to select the customer from the table once they have been added to the database to use as a foreign key in the OrderTable table.
At the moment I have the details of the customer stored in local storage which can easily be accessed, but once the customer is added to the database they will get an ID. This is the only way I could think to select a unique customer.
Insert the customer details first. Then get the ID of the newly inserted customer and use it while inserting the order details!
You could use the LAST_INSERT_ID() after you insert the user details to the db to get the ID of the customer.
Or if you are using PHP, then:
if you're using PDO, use PDO::lastInsertId
if you're using Mysqli, use mysqli::$insert_id
Hope this helps.
I will try to be specific because I feel my understanding of the subject isn't quite precise as well. My problem is understanding how to create relations between tables with foreign keys which I add with alter statements. I have these tables.
CREATE TABLE article (
content TEXT NOT NULL,
published_on DATE NOT NULL,
created_on DATE NOT NULL,
);
CREATE TABLE category(
name VARCHAR(30) NOT NULL,
date_created DATE NOT NULL,
);
CREATE TABLE user(
income FLOAT(30, 30) NOT NULL,
password VARCHAR(30) NOT NULL,
picture_url TEXT NOT NULL,
);
CREATE TABLE tag(
description VARCHAR(30) NOT NULL,
second_priority FLOAT(30, 30) NOT NULL,
);
To which I have to make there relationships:
Tag has a one to one connection to Category
Category has a many to one connection to User
User has a one to many connection to Article
And to do that I use there statements:
ALTER TABLE tag ADD CONSTRAINT FOREIGN KEY (tag_id) REFERENCES category (category_id);
ALTER TABLE category ADD CONSTRAINT FOREIGN KEY (user_id) REFERENCES user (user_id);
ALTER TABLE user ADD CONSTRAINT FOREIGN KEY (user_id) REFERENCES article (user_id);
My problem is that the third one fails. When I switch the places of article and user the constraint passes. After a bit of digging and experimenting I found out that I can't constraint two keys from which one is either UNIQUE or PRIMARY KEY and the other one just NOT NULL. So far I don't know how to continue, can someone please enlighten me as to how to create a one to one, many to one, one to many and a many to many relationship between these tables because I am kinda lost and everything in my head is a mess.
FULL STUFF:
CREATE DATABASE exam_database;
USE exam_database;
CREATE TABLE article (
content TEXT NOT NULL,
published_on DATE NOT NULL,
created_on DATE NOT NULL,
user_id INT(30) NOT NULL
);
CREATE TABLE category(
name VARCHAR(30) NOT NULL,
date_created DATE NOT NULL,
category_id INT(30) NOT NULL PRIMARY KEY AUTO_INCREMENT UNIQUE,
user_id INT(30) NOT NULL
);
CREATE TABLE user(
income FLOAT(30, 30) NOT NULL,
password VARCHAR(30) NOT NULL,
picture_url TEXT NOT NULL,
user_id INT(30) NOT NULL PRIMARY KEY AUTO_INCREMENT UNIQUE
);
CREATE TABLE tag(
description VARCHAR(30) NOT NULL,
second_priority FLOAT(30, 30) NOT NULL,
tag_id INT(30) NOT NULL PRIMARY KEY AUTO_INCREMENT UNIQUE
);
ALTER TABLE tag ADD CONSTRAINT FOREIGN KEY (tag_id) REFERENCES category (category_id);
ALTER TABLE category ADD CONSTRAINT FOREIGN KEY (user_id) REFERENCES user (user_id);
ALTER TABLE user ADD CONSTRAINT FOREIGN KEY (user_id) REFERENCES article (user_id);
First Your structure has some errors:
Missing PK, Why using INT(30)? etc...
Your DB should looks like:
CREATE DATABASE exam_database;
USE exam_database;
CREATE TABLE article (
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT UNIQUE,
user_id INT NOT NULL,
content TEXT NOT NULL,
published_on DATE NOT NULL,
created_on DATE NOT NULL
);
CREATE TABLE category(
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT UNIQUE,
user_id INT NOT NULL,
name VARCHAR(30) NOT NULL,
date_created DATE NOT NULL
);
CREATE TABLE user (
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT UNIQUE ,
income FLOAT(30, 30) NOT NULL,
password VARCHAR(30) NOT NULL,
picture_url TEXT NOT NULL
);
CREATE TABLE tag (
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT UNIQUE,
category_id INT NOT NULL,
description VARCHAR(30) NOT NULL,
second_priority FLOAT(30, 30) NOT NULL
);
Second Your FKs should look like:
ALTER TABLE tag ADD CONSTRAINT FOREIGN KEY (category_id) REFERENCES category (id);
ALTER TABLE category ADD CONSTRAINT FOREIGN KEY (user_id) REFERENCES user (id);
ALTER TABLE article ADD CONSTRAINT FOREIGN KEY (user_id) REFERENCES user (id);
Trying to create a foreign key on table Supplier for Supplier_ID referencing table Payment.
CREATE TABLE Payment (
Supplier_ID INT (4) NOT NULL,
Date DATE NOT NULL,
Amount INT (4),
Payment_ID INT (4) NOT NULL,
PRIMARY KEY (Payment_ID, Supplier_ID)
);
Query OK, 0 rows affected (0.10 sec)
CREATE TABLE Supplier (
Supplier_ID INT(4) NOT NULL,
Name VARCHAR(4) NOT NULL,
Country VARCHAR(4) NOT NULL,
Reliability_Score INT(4),
Contact_Info VARCHAR(4),
PRIMARY KEY (Supplier_ID)
FOREIGN KEY (Supplier_ID) REFERENCES Payment(Supplier_ID)
);
ERROR 1215 (HY000): Cannot add foreign key constraint
Please let me know if I can provide additional information, thank you.
A foreign key has to reference a unique column. So the Supplier_ID column needs to be unique.
However, it seems like you might have it backward if I'm understanding your intention correctly. It should probably be a foreign key on supplier_ID in the Payment table referencing the supplier table.
In the context of relational databases, a foreign key is a field (or collection of fields) in one table that uniquely identifies a row of another table. In other words, a foreign key is a column or a combination of columns that is used to establish and enforce a link between the data in two tables.
in your code u have declared primary key as PRIMARY KEY (Payment_ID, Supplier_ID) which is a combination of two columns which is totally fine but while creating foreign key FOREIGN KEY (Supplier_ID) REFERENCES Payment(Supplier_ID) you are referring one column to a combination of two columns which is wrong
read here http://en.wikipedia.org/wiki/Foreign_Key
now your solution:
first create Supplier table
CREATE TABLE Supplier (
Supplier_ID INT(4) NOT NULL,
Name VARCHAR(4) NOT NULL,
Country VARCHAR(4) NOT NULL,
Reliability_Score INT(4),
Contact_Info VARCHAR(4),
PRIMARY KEY (Supplier_ID)
);
now the payment table
CREATE TABLE Payment (
Supplier_ID INT (4) NOT NULL,
Date DATE NOT NULL,
Amount INT (4),
Payment_ID INT (4) NOT NULL,
PRIMARY KEY (Payment_ID, Supplier_ID),
FOREIGN KEY (Supplier_ID) REFERENCES Supplier(Supplier_ID)
);