Type matches correctly, but why " #1215 - Cannot add foreign key constraint" keeps poping out? - sql

This is my first table "address".
create table address(
street varchar(32) not null,
city varchar(32) not null,
state varchar(32) not null,
zip_code varchar(32) not null,
primary key(zip_code)
)
This is my second table "customer".
create table customer(
customer_id integer not null,
name varchar(32) not null,
primary key(customer_id)
)
This is my relational table about above two tables. But why cannot I make it? The type matches well. So please.
create table cus_live(
customer_id integer not null,
zip_code varchar(32) not null,
primary key(customer_id, zip_code),
foreign key(customer_id) references customer,
foreign key(zip_code) references address
)

This is the correct way to create a foreign key constraint:
create table cus_live(
cus_live_id int not null,
customer_id int not null,
address_id int not null,
primary key(cus_live_id),
foreign key(customer_id) references customer (customer_id),
foreign key(address_id) references address (address_id)
)
Notice the changes I made:
After references [tableName], added the key name in parentheses. This will tell SQL which column is referenced in the foreign key constrant.
Changed the primary key of the table to its own unique id rather than a composite of two columns. Usually this is better practice.
Changed primary key of address table to address_id instead of zipcode. Otherwise you would have conflicts if two customers have the same zipcode but different addresses within that zipcode.
Made your id's integers instead of strings.
Also, note that this is all assuming that cus_live has some other columns that you have excluded (and cannot be included on either the address or customer table) and hence warrants having this third table in the first place. Otherwise you could just put address_id on the customer table like this:
create table address(
address_id int not null,
street varchar(32) not null,
city varchar(32) not null,
state varchar(32) not null,
zip_code varchar(32) not null,
primary key(address_id)
)
create table customer(
customer_id int not null,
name varchar(32) not null,
address_id int not null,
primary key(customer_id)
foreign key(address_id) references address (address_id)
)

Related

Reference to primary key with constraints

I have 2 tables in my database:
CREATE TABLE Apartment
(
StreetName char(50) not null,
Number Integer not null,
Door Integer not null,
Type char(30) not null,
SizeSquareMeter Integer not null,
NID Integer not null FOREIGN KEY REFERENCES Neighborhood(NID)
CONSTRAINT Address PRIMARY KEY (StreetName, Number, Door)
);
CREATE TABLE Resident
(
RID Integer not null PRIMARY KEY,
FirstName varchar(30) not null,
LastName varchar(30) not null,
BirthDate date not null,
Address
);
Now the primary key in apartment is Address and is based on constraint. I want to create a foreign key Address in the Resident table referencing the
primary key Address in the Apartment table.
How can I do that?
Since your primary key in Apartment is made up from three columns, any table wanting to reference Apartment will also need to have ALL three columns to establish a foreign key link.
So you need to change your Resident table to:
CREATE TABLE Resident
(
RID Integer not null PRIMARY KEY,
FirstName varchar(30) not null,
LastName varchar(30) not null,
BirthDate date not null,
StreetName char(50) not null,
Number Integer not null,
Door Integer not null,
);
and then you can add the foreign key constraint:
ALTER TABLE Resident
ADD CONSTRAINT FK_Resident_Apartment
FOREIGN KEY (StreetName, Number, Door) REFERENCES Apartment (StreetName, Number, Door);
The other option would be to add a surrogate column (an artificial, additional column) to Apartment - either as primary key, or (for SQL Server) at least with a unique constraint - so that you could establish the FK link to that surrogate column (using that one, single column - instead of having to replicate three columns of "real" data)

Creation of new table fails with error message "Foreign key constraint is incorrectly formed"

I have 2 SQL statement as follows:
CREATE TABLE IF NOT EXISTS countries
(
country_id INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
country varchar(45) NOT NULL
);
CREATE TABLE IF NOT EXISTS patients
(
p_id INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
p_fname varchar(50) NOT NULL,
p_mname varchar(10) NULL,
p_lname varchar(50) NOT NULL,
age INT NOT NULL,
sex SET ('Male','Female'),
phone_num_mobile varchar(10) NULL,
phone_num_res varchar(7) NULL,
phone_num_office varchar(7) NULL,
email varchar(75) NULL,
addr_house varchar(10) NULL,
addr_street1 varchar(45) NOT NULL,
addr_street2 varchar(45) NULL,
addr_street3 varchar(45) NULL,
addr_city varchar(20) NOT NULL,
addr_country varchar(45) NOT NULL,
occupation varchar(20) NOT NULL,
married BOOLEAN NOT NULL,
FOREIGN KEY(addr_country) REFERENCES countries(country)
);
The first one executes successfully and the second one, which assigns a foreign key to the previous table, fails to execute with the message 'Foreign key constraint incorrectly formed'. I have also tried altering the second query's foreign key field(addr_country) to have the same name as that of the 'countries' table(country) but it were top no avail.
Can anyone please explain me what's going on and suggest me with a solution to this problem?
Thanks in advance.
A foreign key in MariaDB can only reference either a primary key in another table or a unique key. In this case, the countries table already has a primary key, so you can create a unique key on the country column.
Try putting a unique constraint on the country column in the countries table:
CREATE TABLE IF NOT EXISTS countries
(
country_id INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
country varchar(45) NOT NULL
UNIQUE KEY(country)
);
Late edit: As the commentors mentioned, you might want to just reference the country_id primary key instead of the country name. Since no two countries in the world have the same name, either might work in practice.

SQL: Foreign key references a composite primary key

I'm new to SQL and there are a lot of things going on that I still don't seem to quite understand. I have the following table
CREATE TABLE Person
(
First_Name varchar(20) NOT NULL,
Name varchar(20) NOT NULL,
Address varchar(50) NOT NULL,
PRIMARY KEY (First_Name, Name, Address)
);
I know want to create another table that has the primary key from the table Person as foreign key and also as primary key:
CREATE TABLE Purchase
(
No_Installments int,
Rate int,
Person varchar(50) NOT NULL PRIMARY KEY,
CONSTRAINT PFK
FOREIGN KEY (Person) REFERENCES Person (First_Name, Name, Address)
);
For some reason this doesn't work and I get an error every time. I've already looked up the other threads here on stackoverflow, but they don't really seem to help me. What am I doing wrong?
If you have a compound PK made up from three columns, then any child table that wants to establish a foreign key relationship must ALSO have all those 3 columns and use all 3 columns to establish the FK relationship.
FK-PK relationship is an all or nothing proposal - you cannot reference only parts of a primary key - either you reference all columns - or you don't reference.
CREATE TABLE Purchase
(
No_Installments int,
Rate int,
Person varchar(50) NOT NULL PRIMARY KEY,
First_Name varchar(20) NOT NULL,
Name varchar(20) NOT NULL,
Address varchar(50) NOT NULL,
CONSTRAINT PFK
FOREIGN KEY (First_Name, Name, Address)
REFERENCES Person (First_Name, Name, Address)
);
Have an integer primary key, using identity, auto_increment, serial or whatever for your database:
CREATE TABLE Person (
PersonId int identity PRIMARY KEY
First_Name varchar(20) NOT NULL,
Name varchar(20) NOT NULL,
Address varchar(50) NOT NULL,
CONSTRAINT unq_person_3 UNIQUE (First_Name, Name, Address)
);
Then use the identity column for the reference:
CREATE TABLE Purchase (
PurchaseId int identity PRIMARY KEY,
No_Installments int,
Rate int,
PersonId int,
CONSTRAINT PFK
FOREIGN KEY (PersonId) REFERENCES Person (PersonId)
);
Notes:
You really don't want to have to deal with a composite primary key. Have you thought about what the joins will look like?
You don't want a primary key where the values are subject to change. What happens when someone changes his/her name? When someone moves?
Person should not be the primary key in Purchases. Are you only allowing someone to make one purchase?
As noted initially, how you generate such a column varies by database; identity happens to be the way that SQL Server does this.
You probably want to assign a unique ID to each person, not relying on their name to be unique or for an address to be required. That ID will be your Primary key and foreign key. Your purchase table should also have its own id for its primary key -- otherwise because primary keys must be unique, each person can only have one purchase.
CREATE TABLE Person (
id serial NOT NULL,
First_Name varchar(20) NOT NULL,
Name varchar(20) NOT NULL,
Address varchar(50) NOT NULL,
PRIMARY KEY (id));
CREATE TABLE Purchase (
id serial NOT NULL,
No_Installments int,
Rate int,
Person int NOT NULL,
FOREIGN KEY (Person) REFERENCES Person (id),
PRIMARY KEY (id));

How to insert multiple rows into an Order table?

So I set up a simple database and I am at the point where I am trying to test that it is working correctly. I am trying to figure out how I get multiple entries into an Order table. I need to have an order# and be able to order multiple items and use multiple shippers and such. I just can't seem to figure out a way to get the data into my DB properly.
Below is how I have my DB set up. Could someone please explain to me how to get the my test data into the DB.
Here are the reference tables:
CREATE TABLE Product_Table (
ProductID INT NOT NULL,
Product_Name char(50) NOT NULL,
Product_Cost number(9,2) NOT NULL,
Product_In_Stock INT NOT NULL,
CONSTRAINT Products_PK PRIMARY KEY (ProductID)
);
CREATE TABLE Payment_Terms_Table (
PayTermNum INT NOT NULL,
Payment_Time_Frame CHAR(20) NOT NULL,
CONSTRAINT Payment_Terms_PK PRIMARY KEY (PayTermNum)
);
CREATE TABLE Shipper_Table (
ShipperNum INT NOT NULL,
Shipper_Name CHAR(50) NOT NULL,
Shipper_Phone CHAR(22) NULL,
CONSTRAINT ShipperNum_PK PRIMARY KEY (ShipperNum)
);
CREATE TABLE Supplier_Table (
SupplierID INT NOT NULL,
Supplier_Name CHAR(50) NOT NULL,
Sup_Address CHAR(50) NOT NULL,
Sup_City CHAR(20) NOT NULL,
Sup_State CHAR(20) NOT NULL,
Sup_Zip CHAR(9) NOT NULL,
Sup_Phone CHAR(22) NULL,
ShipperNum INT NOT NULL,
PayTermNum INT NOT NULL,
CONSTRAINT Supplier_PK PRIMARY KEY (SupplierID),
CONSTRAINT ShipperNum_Relationship FOREIGN KEY (ShipperNum)
REFERENCES Shipper_Table (ShipperNum),
CONSTRAINT PayTermNum_Relationship FOREIGN KEY (PayTermNum)
REFERENCES Payment_Terms_Table (PayTermNum)
);
Here is my Order table:
CREATE TABLE Order_Table (
OrderID INT NOT NULL,
ProductID INT NOT NULL,
SupplierID INT NOT NULL,
Wholesale_Price NUMBER (9,2) NOT NULL,
Units_Ordered INT NOT NULL,
Order_Date DATE DEFAULT SYSDATE NOT NULL,
Order_Received DATE NULL,
CONSTRAINT Order_PK PRIMARY KEY (OrderID),
CONSTRAINT ProductID_Relationship FOREIGN KEY (ProductID)
REFERENCES Product_Table (ProductID),
CONSTRAINT SupplierID_Relationship FOREIGN KEY (SupplierID)
REFERENCES Supplier_Table (SupplierID)
);
Your problem is that you have a defined one table to hold Orders, so you can have only one Item per Order. Normally we handle this scenario by having two tables: a Header with the information for the whole Order and a Line table for each ordered Item.
CREATE TABLE Order_Header (
OrderID INT NOT NULL,
Order_Date DATE DEFAULT SYSDATE NOT NULL,
Order_Received DATE NULL,
CONSTRAINT Order_PK PRIMARY KEY (OrderID)
)
/
CREATE TABLE Order_Line (
OrderID INT NOT NULL,
LineNo INT NOT NULL,
ProductID INT NOT NULL,
SupplierID INT NOT NULL,
Wholesale_Price NUMBER (9,2) NOT NULL,
Units_Ordered INT NOT NULL,
CONSTRAINT Order_Line_PK PRIMARY KEY (OrderID, LineNo),
CONSTRAINT Order_Line_Header_FK FOREIGN KEY (OrderID)
REFERENCES Order_Header (OrderID)
CONSTRAINT ProductID_Relationship FOREIGN KEY (ProductID)
REFERENCES Product_Table (ProductID),
CONSTRAINT SupplierID_Relationship FOREIGN KEY (SupplierID)
REFERENCES Supplier_Table (SupplierID)
)
/
I have declared a composite primary key because it is easier to understand what's happening.
Now that you have two tables you can easily create orders with more than one line.
On the subject of normal practice, an Order should have a CUSTOMER. That would be an attribute of ORDER_HEADER. Also you have a SHIPPER table but don't use it. Again that would probably be an attribute of ORDER_HEADER.
Also your naming convention is ugly. There's no need to include _TABLE: just name the objects for teh things they represent. Likewise your foreign key needs are opaque; it doesn't matter so much in this toy example but in a real database you will find it helpful to specify the child and parent tables in the FK names.

Created Primary Key on SQL Server not Identified

CREATE TABLE sampProduct
(
Product_ID VARCHAR(15) NOT NULL,
Supplier_ID INT NOT NULL,
Category_ID INT NOT NULL,
Unit_Price DECIMAL(10, 2)
PRIMARY KEY(Product_ID)
)
CREATE TABLE sampMachine
(
M_Product_ID VARCHAR(15) NOT NULL,
Serial_No VARCHAR(15) NOT NULL,
Machine_Model VARCHAR(20),
PRIMARY KEY(M_Product_ID, Serial_No),
FOREIGN KEY(M_Product_ID) REFERENCES sampProduct(Product_ID)
)
CREATE TABLE sampService
(
Service_ID VARCHAR(15) NOT NULL,
Serial_No VARCHAR(15) NOT NULL,
Complaint VARCHAR(40) NOT NULL,
PRIMARY KEY(Service_ID),
FOREIGN KEY(Serial_No) REFERENCES sampMachine(Serial_No)
)
Machine is a subtype of Product. M_ProductID is referencing the primary key of the parent table Product by this key. And Serial_No is used to uniquely identify a Machine. The problem is, I want to create a foreign key from Serial_No into the Service table, since I want to track the serial numbers of the machine (this is because, for example, we can have many machine for each model or type, but each of them has their unique serial numbers), but there is an error for the creation. Can you help me out?
One of the requirements for creating a foreign key is that the table you reference must have a unique key on the columns you want referenced. So in your example in order for it to work you would need a unique key on sampMachine (Serial_No) so that you could create foreign keys to it using just Serial_No. The way you have it now you would need to use M_Product_Id in the table sampService and add it to the foreign key definition.
create table sampService(
M_Product_ID varchar(15) not null,
Service_ID varchar(15) not null,
Serial_No varchar(15) not null,
Complaint varchar(40) not null,
primary key (Service_ID),
foreign key (Serial_No) references sampMachine(m_Product_Id, Serial_No)
)