Locking Order of table with foreign key constraint? - sql

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?

Related

Invalid Foreign Key value in Teradata

I am getting an invalid foreign key value and I cannot figure out what it is, here is the error.
Executed as multiple statements.
STATEMENT 1:
DATABASE completed. 0 rows processed. Elapsed time = 00:00:00.047
STATEMENT 2:
Insert Statement failed. Failed [2700 : 23000] Referential constraint violation: invalid foreign key value.
This happens when I try to insert:
insert into SALE values (1,30.45,'2020-12-31','VMBNH',1,1);
into the SALE Table
Here is the table, and I am also including the inserts that I already put on the table.
CREATE TABLE EQUIPMENT_DETAIL
(
EquipDetailID INT NOT NULL,
Make VARCHAR(20) NOT NULL,
Equipment_Type VARCHAR(20) NOT NULL,
Model VARCHAR(20) NOT NULL,
PRIMARY KEY (EquipDetailID)
);
CREATE TABLE CUSTOMER
(
CustID INT NOT NULL,
CustName VARCHAR(40) NOT NULL,
CustCategory VARCHAR(20) NOT NULL,
PRIMARY KEY (CustID)
);
CREATE TABLE EQUIPMENT
(
SerialNo VARCHAR(20) NOT NULL,
LastInspectedDate DATE NOT NULL,
DateMade DATE NOT NULL,
EquipDetailID INT NOT NULL,
PRIMARY KEY (SerialNo),
FOREIGN KEY (EquipDetailID) REFERENCES EQUIPMENT_DETAIL(EquipDetailID)
);
CREATE TABLE SALE
(
SaleTransID INT NOT NULL,
Price DECIMAL(4,2) NOT NULL,
Sale_Date DATE NOT NULL,
SerialNo VARCHAR(20) NOT NULL,
CustID INT NOT NULL,
SRepID INT NOT NULL,
PRIMARY KEY(SaleTransID),
FOREIGN KEY (SerialNo) REFERENCES EQUIPMENT(SerialNo),
FOREIGN KEY (CustID) REFERENCES CUSTOMER(CustID),
FOREIGN KEY (SRepID) REFERENCES SALES_REP(SRepID)
);
CREATE TABLE RENTAL
(
Price DECIMAL(4,2) NOT NULL,
Rental_Date DATE NOT NULL,
RentTransID INT NOT NULL,
SerialNo VARCHAR(20) NOT NULL,
CustID INT NOT NULL,
SRepID INT NOT NULL,
PRIMARY KEY (RentTransID),
FOREIGN KEY (SerialNo) REFERENCES EQUIPMENT(SerialNo),
FOREIGN KEY (CustID) REFERENCES CUSTOMER(CustID),
FOREIGN KEY (SRepID) REFERENCES SALES_REP(SRepID)
);
CREATE TABLE SALES_REP
(
SRepID INT NOT NULL,
SRepLName VARCHAR(40) NOT NULL,
SRepFName VARCHAR(20) NOT NULL,
Rank_ID VARCHAR(20) NOT NULL,
Mentors_SRepID INT,
PRIMARY KEY (SRepID),
FOREIGN KEY (Mentors_SRepID) REFERENCES SALES_REP(SRepID)
);
insert into EQUIPMENT_DETAIL values (1,'CFT','Drill','B123');
insert into EQUIPMENT_DETAIL values (2,'CFT','Hammer','B124');
insert into EQUIPMENT_DETAIL values (3,'MKT','Saw','M123');
insert into EQUIPMENT_DETAIL values (4'MKT','Wrench','M124');
insert into EQUIPMENT_DETAIL values (5'SNP','Flat Head','S123');
insert into CUSTOMER values (1,'Jim Halpert','A');
insert into CUSTOMER values (2,'Michael Scott','B');
insert into EQUIPMENT values ('KDJHS','2021-01-12','2010-11-11',1);
insert into EQUIPMENT values ('VMBNH','2021-03-05','2007-12-12',2);
insert into EQUIPMENT values ('QIEIR','2021-03-05','2007-12-12',3);
insert into EQUIPMENT values ('PTPYO','2021-03-05','2007-12-12',4);
insert into EQUIPMENT values ('AGSGD','2021-03-05','2007-12-12',5);
I had to drop the foreign key constraint from SALE (SRepID)

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

SQL: "foreign key constraint fails" error message

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

How to properly configure database schema & inserts

So I have the following schema.
CREATE TABLE user_group (
id BIGINT PRIMARY KEY NOT NULL,
user_id BIGINT NOT NULL,
group_table_id BIGINT NOT NULL,
role VARCHAR(255),
CONSTRAINT user_group_user_id_fk FOREIGN KEY (user_id) REFERENCES user(id),
CONSTRAINT user_group_group_table_id_fk FOREIGN KEY (group_table_id) REFERENCES group_table(id)
);
CREATE TABLE group_table
(
id BIGINT PRIMARY KEY NOT NULL,
group_name VARCHAR(255),
group_picture_url VARCHAR(255),
tags VARCHAR(255),
description VARCHAR(255),
event_id BIGINT,
user_group_id BIGINT,
CONSTRAINT group_table_user_group_id_fk FOREIGN KEY (user_group_id) REFERENCES user_group(id)
);
CREATE TABLE user (
id BIGINT PRIMARY KEY NOT NULL,
display_name VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL,
description TEXT NOT NULL,
picture_url VARCHAR(255),
user_group_id BIGINT,
event_response_id BIGINT,
CONSTRAINT user_user_group_id_fk FOREIGN KEY (user_group_id) REFERENCES user_group(id),
);
How can I make it so that this is a valid statement? In the sense that I should be able to create a user_group table, group_table table, or user table without needing the others.
The other question that I have is. Say this statement is valid and the tables exist. How would I insert data into user_group?
INSERT INTO user_group VALUES (1, 2, 3, 'role')
Would require that both a group_table and a user with id's of 2 and 3 respectively already exist upon insert of the value.
How can I make it so that this is a valid statement? In the sense that I should be able to create a user_group table, group_table table, or user table without needing the others.
You can create the tables first, and create the foreign key constraints after. If you try to do both at the same time (like you currently have), you run into a chicken and egg situation.
Here is an example of how you could do it:
CREATE TABLE user_group (
id BIGINT PRIMARY KEY NOT NULL,
user_id BIGINT NOT NULL,
group_table_id BIGINT NOT NULL,
role VARCHAR(255)
);
CREATE TABLE group_table
(
id BIGINT PRIMARY KEY NOT NULL,
group_name VARCHAR(255),
group_picture_url VARCHAR(255),
tags VARCHAR(255),
description VARCHAR(255),
event_id BIGINT,
user_group_id BIGINT
);
CREATE TABLE user (
id BIGINT PRIMARY KEY NOT NULL,
display_name VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL,
description TEXT NOT NULL,
picture_url VARCHAR(255),
user_group_id BIGINT,
event_response_id BIGINT
);
alter table user_group
add constraint user_group_user_id_fk
foreign key (user_id)
references user(id);
alter table user_group
add constraint user_group_group_table_id_fk
foreign key (group_table_id)
REFERENCES group_table(id);
alter table group_table
add constraint group_table_user_group_id_fk
FOREIGN KEY (user_group_id)
REFERENCES user_group(id);
alter table user
add constraint user_user_group_id_fk
FOREIGN KEY (user_group_id)
REFERENCES user_group(id);
The other question that I have is. Say this statement is valid and the tables exist. How would I insert data into user_group?
INSERT INTO user_group VALUES (1, 2, 3, 'role')
Would require that both a group_table and a user with id's of 2 and 3 respectively already exist upon insert of the value.
Yes, the corresponding rows in user (id = 2) and group (id = 3) would have to be inserted prior to attempting the insert into user_group.

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);