SQL: "foreign key constraint fails" error message - sql

I get an error when attempting to insert data into the songs table. I'm not sure why.
Any help would be greatly appreciated. Thanks. This is me adding details so it will let me post haha.
create table artist
(
id int primary key auto_increment,
name varchar(128) not null,
nationality varchar(128)
) ENGINE=InnoDB;
insert into artist (name, nationality) values ('Metallica', 'American');
insert into artist (name, nationality) values ('Rush', 'Canadian');
create table album
(
id int primary key auto_increment,
name varchar (128) not null,
artist int not null,
foreign key (artist) references artist(id),
genre int,
foreign key (genre) references genre(id)
) ENGINE=InnoDB;
insert into album (name, artist, genre) values ('Ride the Lightning', 1, 1);
insert into album (name, artist, genre) values ('Moving Pictures', 2, 2);
create table song
(
id int primary key auto_increment,
name varchar (128) not null,
duration varchar (128),
album int not null,
foreign key (album) references album(id)
) ENGINE=InnoDB;
insert into song (name, duration, album) values ('Fade to Black', '1 min', 1);
insert into song (name, duration, album) values ('Tom Sawyer', '2 min', 2);
create table genre
(
id int primary key auto_increment,
name varchar (128) not null,
description varchar (256)
) ENGINE=InnoDB;
insert into genre (name, description) values ('Rock', 'Lots of drums and guitars');
insert into genre (name, description) values ('Metal', 'Drums and guitars on steroids');

The order of your code is causing the problem. You need to move the
create table genre
(
id int primary key auto_increment,
name varchar (128) not null,
description varchar (256)
) ENGINE=InnoDB;
insert into genre (name, description) values ('Rock', 'Lots of drums and guitars');
insert into genre (name, description) values ('Metal', 'Drums and guitars on steroids');
Up above the "Create table album"

Here is the correct way to do it: HOW TO DO IT
This is some reasons why it did not work:
There is no table "genre" when you try to create table album:
create table album
(
id int primary key auto_increment,
name varchar (128) not null,
artist int not null,
foreign key (artist) references artist(id),
genre int,
foreign key (genre) references genre(id)
) ENGINE=InnoDB;
Here is the DEMO
Also, when you create table "genre" on time, there is another problem. You have to insert data in table "genre" to be able to insert other data.
Here is the DEMO where all works.

One is the order of the create and insert statements shouldve given you error already as table referres doesnt exists etc.
Assuming if the order is rightly implemented, as per the above error not able to insert data in songs is likely because
Your album table has a null id or id which you are inserting in songs doesnt exists in album first insert the data in album table then insert into songs table as the foreign key of songs table is checking the album table for id data

Related

how do i make my foreign key the actual ID instead of it being NULL?

I'm creating two tables and I would like to use UserID in User_info_table as a foreign key in the Trail_info_table, but it keeps showing as NULL.
CREATE TABLE CW2.User_info_table
(
UserID int IDENTITY PRIMARY KEY,
User_name varchar(255),
Email_Address varchar(255) NOT NULL,
User_password varchar(255) NOT NULL,
User_access_level int NOT NULL,
);
INSERT INTO CW2.User_info_table (User_name, Email_Address, User_password, User_access_level)
VALUES ('Grace Hopper', 'grace#plymouth.ac.uk', 'ISAD123!', 1)
INSERT INTO CW2.User_info_table (User_name, Email_Address, User_password, User_access_level)
VALUES ('Tim Berners-Lee', 'tim#plymouth.ac.uk', 'COMP2001!', 1)
INSERT INTO CW2.User_info_table (User_name, Email_Address, User_password, User_access_level)
VALUES ('Ada Lovelace', 'ada#plymouth.ac.uk', 'insecurePassword', 1)
CREATE TABLE CW2.Trail_info_table
(
TrailID int IDENTITY,
Trail_name char(255) NOT NULL,
Trail_owner varchar(255),
Trail_owner_ID int
FOREIGN KEY REFERENCES CW2.User_info_table(UserID),
Trail_difficulty int NOT NULL,
Trail_length int NOT NULL,
CONSTRAINT Trail_primary PRIMARY KEY (TrailID),
);
INSERT INTO CW2.Trail_info_table (Trail_name, Trail_owner, Trail_difficulty, Trail_length)
VALUES ('Spring Sprint', 'Grace Hopper', 1, 10)
INSERT INTO CW2.Trail_info_table (Trail_name, Trail_owner, Trail_difficulty, Trail_length)
VALUES ('Summer Stroll', 'Tim Berners-Lee', 2, 15)
INSERT INTO CW2.Trail_info_table (Trail_name, Trail_owner, Trail_difficulty, Trail_length)
VALUES ('Winter Waltz', 'Ada Lovelace', 3, 20)
I tried to get the UserID (1,2,3) in the Trail_owner_ID column as a foreign key but it keeps showing up as NULL

Foreign key references invalid column error in MS SQL

This is all in MS SQL.
I've seen this issue pop up a lot, and I searched around but I still can't figure out my issue. I'm getting the error telling me my foreign key references in invalid column in an uncreated table. However, I created the table as it shows up on my database table list, so it shows it is created.
I tried to move that said table above the table that references it, yet I'm still receiving the error. Would anyone know how to fix this?
My code:
CREATE SCHEMA usr_in;
go
CREATE TABLE gender_interst (
id int IDENTITY (1,1),
gend_id int
CONSTRAINT gender_interstpk PRIMARY KEY (id)
)
CREATE TABLE gender (
id int IDENTITY (1,1),
gend VARCHAR (20)
CONSTRAINT genderpk PRIMARY KEY (id)
);
SELECT * FROM gender_interst LEFT JOIN gender on gender_interst.id = gender.id;
SELECT * from gender_interst;
CREATE TABLE user_info (
id int PRIMARY KEY IDENTITY (1,1),
usr_name VARCHAR (30) NOT NULL,
f_name VARCHAR (30) NOT NULL,
l_name VARCHAR (30),
b_day DATE,
email VARCHAR (120) NOT NULL,
genderpkid VARCHAR (10) NOT NULL,
CONSTRAINT gender_fk FOREIGN KEY (genderpkid) REFERENCES gender (genderpk),
);
INSERT
INTO user_info
( usr_name, f_name, l_name, b_day, genderpkid, email)
VALUES
('JMAN', 'JOHN', 'DOE', '1990-01-01','M','EX#EMAIL'),
('JAM','JANE', 'DOE', '1995-05-02','F','EX#EMAIL'),
('NMAN','NICK', 'WEBB', '1999-06-22','M','EX#EMAIL'),
('LOBA','LOLA', 'LILLY', '1994-01-08','F','EX#EMAIL'),
('NOTSPMAN','PETER', 'PARKER','1985-11-25','M','EX#EMAIL');
SELECT * FROM user_info;
Your foreign key needs to reference the name of a table column (which is either id or gend) and not the name of the primary key (genderpk).
Therefore the foreign key script (CONSTRAINT gender_fk FOREIGN KEY (genderpkid) REFERENCES gender (genderpk)) should look something like CONSTRAINT gender_fk FOREIGN KEY (genderpkid) REFERENCES gender (id)
However to create the relationship the two columns need to have the same data type. user_info .genderpkid is VARCHAR (10) and user_info.id is int.
The other problem you might encounter is that the insert scripts insert the data into genderpkid column as M or F. Therefore int is not going to work
If you were to use use the values M or F for gender, then you can create a script like:
CREATE TABLE gender (
id VARCHAR (1),
gender VARCHAR (20)
CONSTRAINT gender_pk PRIMARY KEY (id)
);
CREATE TABLE user_info (
id int PRIMARY KEY IDENTITY (1,1),
usr_name VARCHAR (30) NOT NULL,
f_name VARCHAR (30) NOT NULL,
l_name VARCHAR (30),
b_day DATE,
email VARCHAR (120) NOT NULL,
genderId VARCHAR (1) NOT NULL,
CONSTRAINT gender_fk FOREIGN KEY (genderId) REFERENCES gender (id),
);
INSERT INTO gender (id, gender)
VALUES
('F', 'Female'),
('M', 'Male')
INSERT
INTO user_info
( usr_name, f_name, l_name, b_day, genderId, email)
VALUES
('JMAN', 'JOHN', 'DOE', '1990-01-01','M','EX#EMAIL'),
('JAM','JANE', 'DOE', '1995-05-02','F','EX#EMAIL'),
('NMAN','NICK', 'WEBB', '1999-06-22','M','EX#EMAIL'),
('LOBA','LOLA', 'LILLY', '1994-01-08','F','EX#EMAIL'),
('NOTSPMAN','PETER', 'PARKER','1985-11-25','M','EX#EMAIL');
SELECT * FROM user_info;
A better approach could be, to pass the whole phraze (male / female) to the table user_info. The table gender can be used to enforce referential integrity. All your information is then contained in SELECT * FROM user_info
For example:
CREATE TABLE gender (
[name] VARCHAR (20)
CONSTRAINT gender_pk PRIMARY KEY ([name])
);
CREATE TABLE user_info (
id int PRIMARY KEY IDENTITY (1,1),
usr_name VARCHAR (30) NOT NULL,
f_name VARCHAR (30) NOT NULL,
l_name VARCHAR (30),
b_day DATE,
email VARCHAR (120) NOT NULL,
gender VARCHAR (20) NOT NULL,
genderIntrest VARCHAR (20) NOT NULL,
CONSTRAINT gender_fk FOREIGN KEY (gender) REFERENCES gender ([name]),
CONSTRAINT genderIntrest_fk FOREIGN KEY (genderIntrest) REFERENCES gender ([name]),
);
INSERT INTO gender ([name])
VALUES
('Female'),
('Male')
INSERT
INTO user_info
( usr_name, f_name, l_name, b_day, gender, genderIntrest, email)
VALUES
('JMAN', 'JOHN', 'DOE', '1990-01-01','Male','Female', 'EX#EMAIL'),
('JAM','JANE', 'DOE', '1995-05-02','Female','Female', 'EX#EMAIL'),
('NMAN','NICK', 'WEBB', '1999-06-22','Male','Female','EX#EMAIL'),
('LOBA','LOLA', 'LILLY', '1994-01-08','Female','Female','EX#EMAIL'),
('NOTSPMAN','PETER', 'PARKER','1985-11-25','Male','Female','EX#EMAIL');
SELECT * FROM user_info;
You can remove the gender table and let the app that consumes it pass in the data. However for a learning exercises, it's probably better to leave it in

Locking Order of table with foreign key constraint?

If I create a schema such as the following:
create table org
(
org_id bigint not null auto_increment,
name varchar(255) not null,
primary key(org_id)
);
create table user
(
user_id bigint not null auto_increment,
name varchar(255) not null,
org_id bigint not null,
primary key(user_id),
foreign key(org_id) references org (org_id)
);
Where the org table has one entry:
insert into org (name) values ('org 1');
If I run the following sql statement:
insert into user (name, org_id) values ('user 1', 1);
In what order will the tables be locked? Is it deterministic? What if there were a second foreign key constraint to another table?

SQL SELECT FROM TWO TABLES INNER JOIN

I am trying select from my Album and ArtistBand Table and display the Name and Bandname in alphabetical order. When in try to use the select statement below it shows up with all the albums on each band. Any help would be appreciated project for school.
CREATE TABLE ArtistBand
(
ArtistID INT AUTO_INCREMENT PRIMARY KEY,
BandName VARCHAR(255) NOT NULL,
NameOfMembers VARCHAR(255),
NumberOfMembers INT
);
CREATE TABLE Genre
(
GenreID INT AUTO_INCREMENT PRIMARY KEY,
GenreType VARCHAR(255) NOT NULL
);
CREATE TABLE Album
(
AlbumID INT AUTO_INCREMENT PRIMARY KEY,
Name VARCHAR (255) NOT NULL,
ReleaseDate DATE NOT NULL,
Producers VARCHAR (255),
ArtistID INT,
GenreID INT,
FOREIGN KEY(ArtistID) REFERENCES ArtistBand(ArtistID),
FOREIGN KEY (GenreID) REFERENCES Genre (GenreID)
);
CREATE TABLE LookUp
(
AlbumID INT,
GenreID INT,
FOREIGN KEY (AlbumID) REFERENCES Album (AlbumID),
FOREIGN KEY (GenreID) REFERENCES Genre (GenreID)
);
INSERT INTO ArtistBand
VALUES
(NULL,'ACDC','BrianJohnson',4),
(NULL,'Metallica','JamesHeitfield',4),
(NULL,'TheBeatles','JohnLennon',4),
(NULL,'JayZ','ShawnCarter',1),
(NULL,'DangerMouse','BrianBurton',1);
INSERT INTO Album
VALUES
(NULL,'BackInBlack','1980-01-01',NULL,NULL,NULL),
(NULL,'TheBlackAlbum','1991-01-01',NULL,NULL,NULL),
(NULL,'WhiteAlbum','1968-01-01',NULL,NULL,NULL),
(NULL,'TheBlackAlbum','2003-01-01',NULL,NULL,NULL),
(NULL,'TheGreyAlbum','2004-01-01',NULL,NULL,NULL);
INSERT INTO Genre
VALUES
(NULL,'HeavyMetal'),
(NULL,'HeavyMetal'),
(NULL,'Pop'),
(NULL,'HipHop'),
(NULL,'HipHop');
SELECT
ArtistBand.BandName, Album.Name
FROM
ArtistBand
JOIN
Album
ORDER BY
ArtistBand.BandName;
You need to add condition on your join, that the ArtistID should be the same in both tables. So your query will look like below:
SELECT ArtistBand.BandName, Album.Name
FROM ArtistBand
JOIN Album ON ArtistBand.ArtistID = Album.ArtistID
ORDER BY ArtistBand.BandName;

Movie booking: How to let every show have its own set of seats?

I have made a movie booking database in mysql workbench (6.2). This database is then connected to eclipse where I in java have programmed a GUI for the movie booking system.
Everything works well with the GUI/database but there is one logical problem:
If a reservation is made for a show, naturally, the number of seats left in that theater where that show is to be played, will be reduced by 1 for every reservation. But if there is a show that's on a different date but on the same theater then this theaters seats is also reduced by 1 which is wrong.
E.g. a show on Monday should have its own set of seats and one on Tuesday should have its own. A solution could be to create a new column 'nbrseats' in 'shows' but I want it to get its seats from Theaters if that's possible.
Database
set foreign_key_checks = 0;
drop table if exists Users;
drop table if exists Theaters;
drop table if exists Movies;
drop table if exists reservations;
drop table if exists Shows;
create table Theaters (
theatername char(11) not null,
NbrSeats char(20) not null,
primary key (theatername)
)engine innoDB;
create table Movies (
moviename char(30) not null,
primary key (moviename)
)engine innoDB;
create table Shows (
movieDate DATE not null,
theatername char(11) not null,
moviename char(30) not null,
id integer auto_increment,
foreign key (theatername) references Theaters(theatername),
foreign key (moviename) references Movies(moviename),
primary key (id)
)engine innoDB;
create table Users (
username char(20) not null,
fullname char(30) not null,
phonenbr char(10) not null,
address varchar(20) not null,
primary key (username)
) engine innoDB;
create table reservations (
resNbr integer auto_increment,
username char(20) not null,
showId int(30) not null,
foreign key(showid) references Shows(id),
foreign key (username) references Users(username),
primary key (resNbr)
)engine innoDB;
-- insert data into the tables
insert into Users values
('Temp1','Name Name', '0701231231', 'Street1');
insert into Movies values
('Star Wars'),
('Dallas'),
('Falcon Crest');
insert into Theaters values
('Filmstaden', '100'),
('SF', '129'),
('Royal', '120');
insert into Shows values
('20151203','Royal', 'Falcon Crest', null),
('20151003','SF', 'Dallas', null),
('20150803','Filmstaden', 'Star Wars', null);
Thanks!
Just make a new column to store the number of booked seats in the reservations table. Then you can write a query to calculate the number of free seats based on the reservations made and the seats available in this theater.
Example to get free seats of showid 1, with two reservations of 5 and 2 seats:
set foreign_key_checks = 0;
drop table if exists Users;
drop table if exists Theaters;
drop table if exists Movies;
drop table if exists reservations;
drop table if exists Shows;
create table Theaters (
theatername char(11) not null,
NbrSeats char(20) not null,
primary key (theatername)
)engine innoDB;
create table Movies (
moviename char(30) not null,
primary key (moviename)
)engine innoDB;
create table Shows (
movieDate DATE not null,
theatername char(11) not null,
moviename char(30) not null,
id integer auto_increment,
foreign key (theatername) references Theaters(theatername),
foreign key (moviename) references Movies(moviename),
primary key (id)
)engine innoDB;
create table Users (
username char(20) not null,
fullname char(30) not null,
phonenbr char(10) not null,
address varchar(20) not null,
primary key (username)
) engine innoDB;
create table reservations (
resNbr integer auto_increment,
username char(20) not null,
showId int(30) not null,
seats int not null,
foreign key(showid) references Shows(id),
foreign key (username) references Users(username),
primary key (resNbr)
)engine innoDB;
-- insert data into the tables
insert into Users values
('Temp1','Name Name', '0701231231', 'Street1');
insert into Movies values
('Star Wars'),
('Dallas'),
('Falcon Crest');
insert into Theaters values
('Filmstaden', '100'),
('SF', '129'),
('Royal', '120');
insert into Shows values
('20151203','Royal', 'Falcon Crest', null),
('20151003','SF', 'Dallas', null),
('20150803','Filmstaden', 'Star Wars', null);
insert into reservations values
(null,'Temp1', 1, 5),
(null,'Temp1', 1, 2),
(null,'Temp1', 2, 3);
select
Shows.id,
Shows.theatername,
Theaters.NbrSeats,
sum(reservations.seats),
Theaters.NbrSeats-sum(reservations.seats) freeseats
from Shows
left join Theaters
on Shows.theatername = Theaters.theatername
left join reservations
on Shows.id = reservations.showId
where Shows.id = 1
group by
Shows.id,
Shows.theatername,
Theaters.NbrSeats
Database is correct, it was a matter of querying
here is an (somewhat primitive) example query for id = 2:
select nbrseats - (select count(showId) from reservations
where showId = (select id from shows where id = 2)) from theaters
where theatername = (select theatername from shows where id = 2);