SQL - cannot add or update a child row: a foreign key constraint fails - sql

I keep getting the error:
Cannot add or update a child row: a foreign key constraint fails
(myWork.Bookingss, CONSTRAINT Bookingss_ibfk_1 FOREIGN KEY
(CustomersID) REFERENCES Customers (CustomersID))
I have spent a while researching as this is apart of a school assignment and can not seem to resolve the problem.
Here is my SQL code:
USE myWork ;
DROP TABLE IF EXISTS Bookingss ;
DROP TABLE IF EXISTS Customers ;
CREATE TABLE myWork.Customers
(
CustomersID INT NOT NULL AUTO_INCREMENT,
Surname CHAR(30) NOT NULL ,
FirstName CHAR(30) NOT NULL ,
Title CHAR(10),
DOB DATE,
HouseNumber INT,
StreetName CHAR(30),
Town CHAR(30),
PostCode CHAR(9),
Telephone INT,
PRIMARY KEY (CustomersID)
) ;
CREATE TABLE myWork.Bookingss
(
BookingsID INT NOT NULL AUTO_INCREMENT,
CustomersID INT NOT NULL,
AdultsBooked INT NOT NULL,
ChildrenBooked INT NOT NULL,
Check_In DATE,
Check_Out DATE,
PRIMARY KEY (BookingsID),
FOREIGN KEY (CustomersID)
REFERENCES myWork.Customers (CustomersID)
) ;
SHOW TABLES ;
INSERT INTO myWork.Bookingss ( CustomersID, AdultsBooked , ChildrenBooked , Check_In , Check_Out )
VALUES ("1", "2", "3", "2022-04-10", "2022-04-13" ) ;
INSERT INTO myWork.Customers ( Surname , FirstName , Title , DOB )
VALUES ( "smith" , "ryan" , "Mr" , "1998-02-16" ) ;
SELECT * FROM Customers , Bookingss;

You got the order wrong and some challenges to overcome. You are trying to insert a booking first, and this with an id for a customer that does not yet exist in the customer table at that moment.
You have to insert the customer first, then use the customer's id to insert the booking for the customer (using his id).
And there is the first challenge. The customer id is an auto increment field. You would not know the id when you insert a customer in the table.
You would have to fetch the customer and use the id of that customer to insert a booking for the customer. How do you fetch the customer? Selecting the customer with a specific name surname and first name is not a correct choice, any other field (or composition of fields) that I see in the table definition is not a good choice neither.
You'd need to think further about a good solution. There are several options I could tell you about. But the appropriate solution depends on your assignment/context.
By the way, the last select clause may not deliver the result you expect. You are producing a cartesian product (every row of the first table with every row of the second table). What you probably want is a JOIN where you link the first table with the second table accordingly (e.g. using the primary key and the foreign key).

Related

Get true or false if Records present table having two foreign Key along with both table record

I do not have much experience in SQL. trying to work out query as below:
i have three table A,B and C. table C have foreign key from table A and table B.
table A => Employee details,
table B => Training Details,
table C => save which Employee has completed which training.
so need basically fetch Employee Name(All), Training Name(All), True if Emp. completed particular Training or else false.
select distinct innerEmp.EmployeeID, innerEmp.FirstName + ' ' + innerEmp.LastName as EmpName,
innerTrain.TrainingID, innerTrain.TrainingName
from tblEmployee innerEmp, tblTraining innerTrain
Above giving me first two column. but table tblEmployeeTraining (table C) how to get third column (True if Emp. completed particular Training or else false).
Example
create table student(
snum numeric(9,0) primary key,
sname varchar(30),
major varchar(25),
standing varchar(2),
age numeric(3,0)
);
create table class(
name varchar(40) primary key,
meets_at varchar(20),
room varchar(10),
fid numeric(9,0),
);
create table enrolled(
snum numeric(9,0),
cname varchar(40),
primary key(snum,cname),
foreign key (snum) references
student(snum),
foreign key (cname) references
class(name)
);
Result i expect below:
Please Help

Beginner with triggers

Im a beginner in database and i got this difficult auction database project.
Im using SQL Server Management Studio also.
create table user(
name char(10) not null,
lastname char(10) not null
)
create table item(
buyer varchar(10) null,
seller varchar(10) not null,
startprice numeric(5) not null,
description char(22) not null,
start_date datetime not null,
end_date datetime not null,
seller char(10) not null,
item_nummer numeric(9) not null,
constraint fk_user foreign key (buyer) references user (name)
)
Basically what the rule im trying to make here is:
Column buyer has NULL unless the time (start_date and end_date) is over and startprice didnt go up or increased. Then column buyer will get the name from table user who bidded on the item.
The rule is a bid too difficult for me to make, i was thinking to make a trigger, but im not sure..
Your model is incorrect. First you need a table to store the bids. Then when the auction is over, you update the highest one as the winning bid. Proably the best way is to have a job that runs once a minute and finds the winners of any newly closed auctions.
A trigger will not work on the two tables you have because triggers only fire on insert/update or delete. It would not fire because the time is past. Further triggers are an advanced technique and a db beginner should avoid them as you can do horrendous damage with a badly written trigger.
You could have a trigger that works on insert to the bids table, that updates the bid to be the winner and takes that status away from the previous winner. Then you simply stop accepting new bids at the time the auction is over. Your application could show the bidder who is marked as the winner as the elader if the auction is till open and teh winner if it is closed.
There are some initial problems with your schema that need addressed before tackling your question. Here are changes I would make to significantly ease the implementation of the answer:
-- Added brackets around User b/c "user" is a reserved keyword
-- Added INT Identity PK to [User]
CREATE TABLE [user]
(
UserId INT NOT NULL
IDENTITY
PRIMARY KEY
, name CHAR(10) NOT NULL
, lastname CHAR(10) NOT NULL
)
/* changed item_nummer (I'm not sure what a nummer is...) to ItemId int not null identity primary key
Removed duplicate Seller columns and buyer column
Replaced buyer/seller columns with FK references to [User].UserId
Add currentBid to capture current bid
Added CurrentHighBidderId
Added WinningBidderId as computed column
*/
CREATE TABLE item
(
ItemId INT NOT NULL
IDENTITY
PRIMARY KEY
, SellerId INT NOT NULL
FOREIGN KEY REFERENCES [User] ( UserId )
, CurrentHighBidderId INT NULL
FOREIGN KEY REFERENCES [User] ( UserId )
, CurrentBid MONEY NOT NULL
, StartPrice NUMERIC(5) NOT NULL
, Description CHAR(22) NOT NULL
, StartDate DATETIME NOT NULL
, EndDate DATETIME NOT NULL
)
go
ALTER TABLE dbo.item ADD
WinningBidderId AS CASE WHEN EndDate < CURRENT_TIMESTAMP
AND currentBid > StartPrice THEN CurrentHighBidderId ELSE NULL END
GO
With the additional columns a computed column can return the correct information. If you must return the winner's name instead of id, then you could keep the schema above the same, add an additional column to store the user's name, populate it with a trigger and keep the computed column to conditionally show/not show the winner..

How can I insert a set of child records while updating the parent?

I'm using SQL Server 2005 and wish to create a number address records, updating the contact records with the new Id's:
Take the following tables
create table contact(id int primary key identity, home_address_id int, work_address_id int)
create table address(id int primary key identity, street varchar(25), number int)
And foreign keys:
ALTER TABLE dbo.contact ADD CONSTRAINT FK_contact_address1 FOREIGN KEY (home_address_id) REFERENCES dbo.address(id)
ALTER TABLE dbo.contact ADD CONSTRAINT FK_contact_address2 FOREIGN KEY (work_address_id) REFERENCES dbo.address(id)
some dummy data
insert into contact default values
insert into contact default values
insert into contact default values
How can I insert a default empty address record for all contacts who have no home address, and update the home_address_id in one go?
The first part is simple:
insert into address(street) select null from contact where home_address_id is null
I can even get the newly create address id's:
declare #addressTable table(id int)
insert into address(street)
OUTPUT INSERTED.Id INTO #addressTable
select null from contact where home_address_id is null
Here's the new id's
select * from #addressTable
But how to update the contact table with these new Id's?
If possible, I would suggest normalizing your database by adding a Contact_Addresses table:
CREATE TABLE Contact_Addresses
(
contact_id INT NOT NULL,
address_id INT NOT NULL,
address_type VARCHAR(10) NOT NULL,
CONSTRAINT PK_Contact_Addresses PRIMARY KEY CLUSTERED (contact_id, address_id, address_type),
CONSTRAINT FK_ContactAddresses_Contacts (contact_id) REFERENCES Contacts (id),
CONSTRAINT FK_ContactAddresses_Addresses (address_id) REFERENCES Addresses (id),
CONSTRAINT CK_ContactAddresses_address_type CHECK address_type IN ('HOME', 'WORK')
)
Next, I would suggest not putting "dummy" records in your database. It's going to end up causing headaches down the road. The database should contain an accurate record of the data in your system. If you want to display some value by default when no address exists in the system for a contact then handle that in your UI.
If you really must though, then the following code should do the trick:
;WITH C_CTE AS
(
SELECT
id,
home_address_id,
ROW_NUMBER() OVER(ORDER BY id) AS seq
FROM
Contacts
),
(
SELECT
id,
ROW_NUMBER() OVER(ORDER BY id) AS seq
FROM
Addresses
)
UPDATE
C_CTE
SET
home_address_id = A.id
FROM
C_CTE C
INNER JOIN A_CTE A ON A.seq = C.seq
I would do it from the moment you get a new contact, thusly:
[receive contact information]
//prior to inserting contact
declare #homeAddress int, #workAddress int
[insert home address here (real or default based on input)]
set #homeAddress = ##Identity
[insert work address here (real or default)]
set #workAddress = ##Identity
[insert contact here referencing #homeAddress & #workAddress]
For the stuff already in your table, you're going to have to associate all of your null value ids to a contact id. Or, you could clear out your null value addresses, and modify the above statement to an update somehow (brain's not working at the moment, so all I'm coming up with is a cursor, and cursors are evil).

Why does this query only select a single row?

SELECT * FROM tbl_houses
WHERE
(SELECT HousesList
FROM tbl_lists
WHERE tbl_lists.ID = '123') LIKE CONCAT('% ', tbl_houses.ID, '#')
It only selects the row from tbl_houses of the last occuring tbl_houses.ID inside tbl_lists.HousesList
I need it to select all the rows where any ID from tbl_houses exists within tbl_lists.HousesList
It's hard to tell without knowing exactly what your data looks like, but if it only matches the last ID, it's probably because you don't have any % at the end of the string, so as to allow for the list to continue after the match.
Is that a database in zeroth normal form I smell?
If you have attributes containing lists of values, like that HousesList attribute, you should instead be storing those as distinct values in a separate relation.
CREATE TABLE house (
id VARCHAR NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE list (
id VARCHAR NOT NULL,
PRIMARY KEY (id),
);
CREATE TABLE listitem (
list_id VARCHAR NOT NULL,
FOREIGN KEY list_id REFERENCES list (id),
house_id VARCHAR NOT NULL,
FOREIGN KEY house_id REFERENCES house (id),
PRIMARY KEY (list_id, house_id)
);
Then your distinct house listing values each have their own tuple, and can be selected like any other.
SELECT house.*
FROM house
JOIN listitem
ON listitem.house_id = house.id
WHERE
listitem.list_id = '123'

need help in primary key and foreign key

I need help in auto populating the primary key values in foreign key table while inserting data in foreign key table. For Example: I have created table:
create table Patient
(
PatientId int IDENTITY(1,1) primary key,
FirstName varchar(50),
SurName varchar(50),
Gender char(20),
)
Say 5 rows are there in this Patient Table:
Say First Row value is: 1, Priya, Kumari, Female
I have created the Guardians Table:
create table Guardians
(
GuardiansId int identity(1,1) primary key,
PatientId int foreign key references Patient(PatientId),
FirstName varchar(50),
SurName varchar(50),
Gender char(20),
RelationToPatient varchar(50),
)
In this table Insert operations are like this:
insert into Guardians(FirstName, SurName, Gender,RelationToPatient)values('Sumit','Kumar','Male','Wife')
While selecting the Guardians Table PatientId showing NULL values: My query is while inserting the values in Guardians Table PatientId should be auto Populated which will come from Patient Table...
My second problem is: How to create the Identity column as varchar. For example: suppose I want to increment my Guardians Table with 'GRD0001', 'GRD0002', 'GRD0003' like this...
Thanks,
S.D
Your question is not very clear - what exactly do you want to do??
When you insert something into the Guardians table, you want to automatically also insert it into the Patients table? I don't quite follow. Can you make a complete example, maybe??
If you need to capture the insert IDENTITY value from the Patient table, do this:
DECLARE #NewPatientID INT
INSERT INTO dbo.Patient(fields) VALUES(.......)
SET #NewPatientID = SCOPE_IDENTITY()
INSERT INTO dbo.Guardians(PatientId, ......) VALUES(#NewPatientID, ......)
As for your second question: leave you GuardiansId IDENTITY as it is (only an INT column can be an IDENTITY and you want to keep that - trust me!) and add a computed column to your table:
ALTER TABLE dbo.Guardians
ADD GuardianIDWithPrefix AS
'GDR' + RIGHT('0000' + CAST(GuardiansId AS VARCHAR(4)), 4) PERSISTED
Since it's a PERSISTED field, you can even index on it and use it like a normal field in every respect.
That should do the trick!