I'm very new to SQL, I'm trying to define a 2 tables Hospital and Hospital_Address but when I'm trying to add foreign key in Hospital_Address it throws an error: "1215: Cannot add foreign key"
create table Hospital (
HId Int not null,
HName varchar(40) not null,
HDept int, Hbed Int,
HAreaCd int not null,
Primary Key (HId)
);
create table Hospital_Address (
HAreaCd Int not null,
HArea varchar(40) not null,
HCity varchar(40),
HAdd1 varchar(40),
HAdd2 varchar(40),
Primary Key (HArea),
foreign key (HAreaCd) references Hospital (HAreaCd));
Please help me in this regard. Thanks in advance.
MySQL requires that there be an index on the HAreaCd column in the parent Hospital table, in order for you to reference that column in a FOREIGN KEY constraint.
The normative pattern is for the FOREIGN KEY to reference the PRIMARY KEY of the parent table, although MySQL extends that to allow a FOREIGN KEY to reference a column that is a UNIQUE KEY, and InnoDB extends that (beyond the SQL standard) and allows a FOREIGN KEY to reference any set of columns, as long as there is an index with those columns as the leading columns (in the same order specified in the foreign key constraint.) (That is, in InnoDB, the referenced columns do not need to be unique, though the behavior with this type of relationship may not be what you intend.)
If you create an index on that column in Hospital table, e.g.:
CREATE INDEX Hospital_IX1 ON Hospital (HAreaCd);
Then you can create a foreign key constraint that references that column.
However, because this is a non-standard extension of MySQL and InnoDB, the "best practice" (as other answers here indicate) is for a FOREIGN KEY to reference the PRIMARY KEY of the foreign table. And ideally, this will be a single column.
Given the existing definition of the Hospital table, a better option for a foreign key referencing it would be to add the Hid column to the Hospital_Address table
... ADD HId Int COMMENT 'FK ref Hospital.HId'
... ADD CONSTRAINT FK_Hospital_Address_Hospital
FOREIGN KEY (HId) REFERENCES Hospital (HId)
To establish the relationship between the rows, the values of the new HId column will need to be populated.
You cannot add a foreign key to a non-primary key element of another table usually.
If you really need to do so, refer to this question for help : Foreign Key to non-primary key
HAreaCd in the Hospital table should be a primary key. Only then can you reference it in the Hospital_Address table
Related
I've always thought that if I were going to use a foreign key that referenced a composite primary key, I'd need to include all the columns of the composite primary key in both tables.
I was confused when I inadvertently didn't do this and received no errors. In the example below, RoomId ISN'T unique, and yet it's allowed to be used as a foreign key by itself.
CREATE TABLE Buildings (
BuildingName VARCHAR(4) PRIMARY KEY,
CampusId TINYINT,
StreetAddress VARCHAR(50),
City VARCHAR(30),
State CHAR(2),
Zip CHAR(5)
);
CREATE TABLE Rooms (
RoomId VARCHAR(5),
BuildingName VARCHAR(20) NOT NULL,
RoomType VARCHAR(15),
Capacity INT,
Notes VARCHAR(100),
CONSTRAINT FK_Buildings_Rooms FOREIGN KEY (BuildingName) REFERENCES Buildings(BuildingName),
PRIMARY KEY (RoomId, BuildingName)
);
CREATE TABLE Instructors(
EmployeeId INT AUTO_INCREMENT PRIMARY KEY,
OfficeId VARCHAR(5),
CONSTRAINT Fk_Instructors_Rooms FOREIGN KEY (OfficeId) REFERENCES Rooms(RoomId));
If I switch the order in the composite primary key to (BuildingName, RoomId), then the foreign key declaration produces the expected error:
Error Code: 1822. Failed to add the foreign key constraint. Missing index for constraint 'Fk_Instructors_Rooms' in the referenced table 'rooms'
MySQL has extended the traditional definition of foreign keys. In most databases, they are limited to unique or primary keys. As with some other "extensions", the documentation explicitly warns against referring to a non-unique key:
However, the system does not enforce a requirement that the referenced columns be UNIQUE or be declared NOT NULL. The handling of foreign key references to nonunique keys or keys that contain NULL values is not well defined for operations such as UPDATE or DELETE CASCADE. You are advised to use foreign keys that reference only UNIQUE (including PRIMARY) and NOT NULL keys.
Of course, not including all the components of a composite key means that you are using a non-unique key.
Your issue with composite primary keys is an interesting one. Personally, I would chalk it up as yet another reason to use auto-incremented primary keys. Single columns are less prone to error in foreign key declarations.
Foreign keys do not need to reference unique or primary key fields. They can reference the first field(s) of any index (primary, unique, or plain).
I am getting ERROR CODE 1215: cannot add foreign key constraint for the child table.
Parent table has composite primary key. I want to use that composite primary key as foreign key in the child table.
Please guide me.
PARENT TABLE
CREATE TABLE health.procedures(
Specialty varchar(40),
Procedure_Name varchar(60),
PRIMARY KEY (Procedure_Name, Specialty)
);
CHILD TABLE
CREATE TABLE health.procedureProvided(
specialization varchar(40),
procedure_name varchar(60),
Insurance_ID int REFERENCES health.insurance (idInsurance),
Hospital_ID int REFERENCES health.hospital (idHospital) ,
Doctor_ID int REFERENCES health.doctor( idDoctor) ,
CONSTRAINT procedures_fk foreign key (specialization,procedure_name)references health.procedures(Specialty,Procedure_Name) ,
PRIMARY KEY (specialization, procedure_name, Insurance_ID, Hospital_ID, Doctor_ID)
);
You are specifying a foreign key that is invalid. Your primary key is procedure_name in health.procedure, but you are trying to create a composite foreign key in health.procedureProvided. You can't create that as a foreign key as the column Specialty in the master table is not part of the primary. A foreign key must contain all the columns in the contributing table's primary key but cannot contain values that are not in that primary key. You have three real options. 1. Specify Specialty as being a component of the primary key in procedure. Unfortunately that means the procedure will not necessarily by unique, it will be unique by specialty. 2. add a surrogate key - a system generated sequence value, uuid or something else (timestamps are not recommended). 3. Create validation tables valid_procedures and valid_specialties and use the table health.procedure as an intersection between those to provide valid procedures and correlated specialties and then you could migrate the entire primary key.
I have a general question about constraint.
What are the difference between the following examples?
CREATE TABLE Orders (
OrderID int NOT NULL PRIMARY KEY,
OrderNumber int NOT NULL,
PersonID int FOREIGN KEY REFERENCES Persons(PersonID)
);
CREATE TABLE Orders (
OrderID int NOT NULL,
OrderNumber int NOT NULL,
PersonID int,
PRIMARY KEY (OrderID),
CONSTRAINT FK_PersonOrder FOREIGN KEY (PersonID)
REFERENCES Persons(PersonID)
);
Thank you!
There is no logical difference.
Standard SQL supports both forms of declaring constraints: at the column level, as in your first example, and at the table level, in your second example.
Table level constraint syntax is needed if you have a primary key or foreign key that involves more than one column.
MySQL supports both column-level and table-level syntax for PRIMARY KEY. But if you subsequently run SHOW CREATE TABLE Orders you will see that MySQL reports it back as if it was declared as a table-level constraint.
MySQL supports only table-level syntax for FOREIGN KEY.
It has been a long-time feature request to support column-level FOREIGN KEY syntax, but so far it has not been implemented. https://bugs.mysql.com/bug.php?id=4919
In the first example, The database will name the constraints implicitly.
In the second example, the create table statement sets the name of the foreign key constraint explicitly. (the primary key should also be named but it's not in this example)
As best practice, you should always give your constraints meaningful names.
I'm attempting to setup a foreign key in table cell_lines that will reference the topographic_region column of the composite primary key in table topographic_regions.
Each time I run the last three lines of code trying to add the foreign key, I receive Error Code 1215: cannot add foreign key constraint.
Now, the foreign key column name (topographic_region) in cell_lines only matches one of the composite primary key column names in topographic_regions, the other composite primary key column name being topographic_region_id. Do I usually need to address both components of a composite primary key when creating a foreign key?
A follow up problem is that I've actually already tried addressing both components of a composite primary key using a composite foreign key constraint, and I was still presented with an Error Code 1215: cannot add foreign key constraint.
What can I do to solve this problem, and is there anymore information you would like me to provide in order to do so? I'm happy to respond.
Thanks for reading. I'm very new to mySQL.
create table topographic_regions(
topographic_regions_id int not null auto_increment,
topographic_region int(10),
karyotypes varchar(255),
constraint pk_topographicID primary key (topographic_regions_id, topographic_region)
);
create table cell_lines(
cell_lines_id int not null auto_increment,
cell_line varchar(50),
topographic_region int(10),
constraint pk_cellID primary key (cell_lines_id, cell_line)
);
alter table cell_lines
add foreign key (topographic_region)
references topographic_regions(topographic_region);
This is the problem with composite PKs. In fact, your autonumber topographic_region_id will be unique and you should use that for the PK, and the FK. topographic_region sounds like it is also unique so you should add a unique index to it.
A foreign key is some columns whose subrow values have to appear as subrow values in another table where they are a candidate key. If you really had a foreign key from cell_lines to topographic_regions then cell_lines would have a topographic_region_name column and you would need:
alter table cell_lines
add foreign key (topographic_regions_id, topographic_region)
references topographic_regions(topographic_regions_id, topographic_region);
I suspect that (topographic_regions_id, topographic_region) is not a candidate key of topographic_regions and that topographic_regions_id is enough to identify a region just because you decided cell_lines doesn't have a topographic_region column. Although it may be that a cell line doesn't identify a particular topographic region. But then topographic_regions_id is not a foreign key in cell_lines, since it isn't a key in topographic_regions. (There is no easy way in SQL to constrain that some columns' subrow values have to appear as subrow values in another table where they are not a superset of a candidate key.)
If topographic_regions_id is unique in topographic_regions then it is a candidate key and should be declared UNIQUE NOT NULL. If topographic_region_name is unique in topographic_regions then it is a candidate key and should be declared UNIQUE NOT NULL. If either is a candidate key then (topographic_regions_id, topographic_region) is not a candidate key. You can pick one candidate key to be declared PRIMARY KEY which just means UNIQUE NOT NULL. Ditto for cell_line. Since your _id columns are auto_increment, I suspect they are unique, in which case neither table has a composite candidate key.
(All this assuming none of your columns can be NULL.)
I am having problems with 2 tables.
I just created a table called "ejemplar" with the following SQL code:
CREATE TABLE ejemplar
(
id_revista INT NOT NULL,
id_ejemplar INT NOT NULL,
id_art INT NOT NULL,
fecha_ejem VARCHAR (30),
precio_ejem decimal,
num_pag_ejem INT,
PRIMARY KEY (id_revista,id_ejemplar,id_art),
FOREIGN KEY (id_revista) REFERENCES revista (id_rev)
)
And I want to create a table called "ejem_art" with the following SQL code:
CREATE TABLE ejem_art(
id_rev INT NOT NULL,
id_ejem INT NOT NULL,
id_art INT NOT NULL,
num_pag INT,
PRIMARY KEY (id_rev,id_ejem,id_art),
FOREIGN KEY (id_rev) REFERENCES revista (id_rev),
FOREIGN KEY (id_ejem) REFERENCES ejemplar (id_ejemplar),
FOREIGN KEY (id_art) REFERENCES articulo (id_art)
);
The DBMS is MySQL and as you can see I have the same type of data in the PK and FK fields in both tables.
When I try to run the second SQL code after creating the table "ejemplar" MySQL shows the famous errno: 150 which relates to different type of data or even different engine rather than InnoDB.
I have made sure both things are correct (same data type and same engine) but I still cannot run the second code.
Hope you could help me with this, because I would not want to make an "Alter Table" just because of this error.
Thanks in advance!
The column you reference in the foreign key must be the leftmost column in a key of the parent table.
CREATE TABLE parent ( A INT, B INT, PRIMARY KEY (A,B) );
CREATE TABLE child (B INT, FOREIGN KEY (B) REFERENCES parent(B) ); /* WRONG */
CREATE TABLE child (A INT, FOREIGN KEY (A) REFERENCES parent(A) ); /* RIGHT */
Re your comments:
It doesn't matter what order the columns are defined in the tables. It matters what order the columns are listed in the PRIMARY KEY constraint. The foreign key can reference only the leftmost column of the parent's key.
In your parent table, you have this primary key:
PRIMARY KEY (id_revista,id_ejemplar),
The column id_revista is leftmost. The column id_ejemplar is not leftmost.
Therefore the child table's foreign key cannot do this:
FOREIGN KEY (id_ejem) REFERENCES ejemplar (id_ejemplar), /* WRONG */
The best solution is to reference both id_revista and id_ejemplar. Then you will be referencing a set of columns of the parent's primary key, starting with the leftmost.
FOREIGN KEY (id_rev, id_ejem) REFERENCES ejemplar (id_revista, id_ejemplar),