I would like that my relation table "In" has a Foreign key SSN which references to two tables, but the SSN is only in one of these two tables.
When I do this:
ALTER TABLE "In"
ADD CONSTRAINT in_C1 FOREIGN KEY (SSN) REFERENCES patient(SSN),
ADD CONSTRAINT in_C2 FOREIGN KEY (SSN) REFERENCES patientWithDoD(SSN)
Then the SSN must be in the table patient and patientWithDoD. The SSN should be in one of the two tables, but not both. How can I do this?
When a column has a non-null value all related foreign key constraints are checked and validated. If the check fails, the row cannot be inserted or updated.
If you have two FKs and you want only one of them to be enforced, then you'll need to:
create two separated nullable columns, one for each FK, and
add a CHECK constraint to enforce one and only one is not null.
For example:
create table "In" (
id int primary key not null,
ssn int, -- nullable
ssn_dod int, -- nullable
constraint fk1 foreign key (ssn) references patient (ssn),
constraint fk2 foreign key (ssn_dod) references patientwithdod (ssn),
constraint chk1 check (ssn is null and ssn_dod is not null or
ssn is not null and ssn_dod is null)
);
Unfortunately, MySQL just recently started to enforce the CHECK constraints (MySQL 8.0.3 if I remember well). If you are using an older version of MySQL, you are out of luck: MySQL will allow you to write the constraint and save it, but won't enforce it.
I understand that you don't have a SSN attribute on patientWithDoD table. To reference a foreign key you have to add this attribute to this table.
You recommend you, add only necessary attributes to the patient table. For ex: ssn, name, surname etc.
Then don't add name, surname and other patient attributes to patientWithDod table. You can use only ssn to refer remaining patient data. So add foreign key that ssn refers to Patient.ssn
This structure would be better and you don't have to refer patienWithDod table.
Related
Title says pretty much what I need but I want to see how I can take two foreign key constraints from a table, and two check constraints and associate one check constraint, while associating the second check constraint with the second foreign key constraint.
Example, I have two 3 tables, item, action, risk. Item references action or risk, by itemid only I want conditional references on more than one foreign key with each foreign key having one unique check constraint.
I will use itemtype ( 'Action' or 'Risk') in my check constraint to determine what table I am referencing.
Here is my command:
ALTER TABLE `projectaim`.`items`
ADD CONSTRAINT `fk_item_risk` FOREIGN KEY (`ItemID`) REFERENCES `projectaim`.`risks`(`RiskID`)
ADD CONSTRAINT ck_item_type CHECK (itemtype = 'Risk')
Is this at all possible in MySQL?
It sounds like you're trying to implement polymorphic-associations, where a given column can be an id referencing any of several parent table.
A foreign key constraint references one parent table. You can't make these conditional. This is why polymorphic associations are fundamentally not compatible with relational constraints.
If you need to reference one of several parent tables, one way to do it is to create multiple columns, each of which are nullable. Then you can use a check constraint or a trigger to make sure that exactly one of them is not null.
CREATE TABLE items (
Itemid INT NOT NULL PRIMARY KEY,
Itemtype ENUM ('Action', 'Risk') NOT NULL,
Actionid INT NULL,
Riskid INT NULL,
FOREIGN KEY (Actionid) REFERENCES actions (Actionid),
FOREIGN KEY (Riskid) REFERENCES risks (riskid),
CHECK (CASE Itemtype
WHEN 'Action' THEN Actionid IS NOT NULL AND Riskid IS NULL
WHEN 'Risk' THEN Riskid IS NOT NULL AND Actionid IS NULL
END)
);
See also:
Possible to do a MySQL foreign key to one of two possible tables?
Why can you not have a foreign key in a polymorphic association?
MySQL - Conditional Foreign Key Constraints
I want to know how to use a foreign key in a table,
I have a code here:
create table penerbit_buku(
id_buku char(8),
foreign key(id_buku) references buku(id_buku),
id_penerbit char(3),
foreign key(id_penerbit) references penerbit(id_penerbit)
)
Can I use this code instead:
create table penerbit_buku(
id_buku char(8) references buku(id_buku),
id_penerbit char(3) references penerbit(id_penerbit)
)
I have tried both and it succeed, is that correct?
No, MySQL parses but ignores the standard inline REFERENCES syntax.
When you declare a foreign key along with an individual column definition, it accepts the syntax as legitimate SQL, but then does not store the foreign key constraint. There's no error reported, but it's as if you didn't write the foreign key syntax at all.
You must declare foreign keys as table-level constraints (your first example above).
This is a case where MySQL is missing a feature of standard SQL. The issue was reported back in 2004, but never fixed! https://bugs.mysql.com/bug.php?id=4919
The reason for this issue is that historically, foreign key constraints were not supported by MySQL itself, but by the InnoDB storage engine, which was made by another company back then. They had to implement their own parser for CREATE TABLE and ALTER TABLE to support foreign keys, and they didn't feel like going the extra steps to support inline foreign key syntax, when table-level foreign key syntax would work.
The architect of InnoDB posted this response:
[6 Sep 2006 10:03] Heikki Tuuri
This will be fixed in MySQL foreign keys, when they are available for all table types.
The MySQL project is gradually working their way toward integrating foreign keys and similar features directly into the MySQL product. Perhaps in a few more years we'll see better support for standard FK syntax.
EXAMPLE:
CREATE TABLE Orders (
ID int NOT NULL,
Number int NOT NULL,
PersonID int,
PRIMARY KEY (ID),
FOREIGN KEY (PersonID) REFERENCES Persons(PersonID)
);
The foreign key must be referencing a primary key in another table
create table penerbit_buku
(id_buku char(8),
id_penerbit char(3),
foreign key(id_buku) references buku(id_buku),
foreign key(id_penerbit) references penerbit(id_penerbit)
);
I would need to see your other tables to give better help in the code
You can use this:
ALTER TABLE `table1`
ADD CONSTRAINT `FK_table1_table2` FOREIGN KEY (`fk_id`) REFERENCES `table2` (`id`);
first lets look at the description of FOREIGN KEY.
A FOREIGN KEY is a key used to link two tables together.
or
A FOREIGN KEY is a field (or collection of fields) in one table that refers to the PRIMARY KEY in another table.
Usually a table that has the foreign key is the child table. and the other table is the reference or parent table.
Since i Can not see your tables, ill give you different example.
Look at the following two tables:
Persons table:
Personal_id LastName FirstName age
1 pretty bob 20
2 angry jack 30
3 happy sue 28
Order Table:
OrderID OrderNumber Personal_id
1 77895 3
2 44678 3
3 22456 2
4 24562 1
Now look how Personal_id column in Orders table points to Personal_id in persons table.
The Personal_id in persons table is the primary key and the Personal_id in the orders table is the FOREIGN KEY.
now except linking how does foreign key help:
two general ways that i can think of:
1- foreign key is like a constrain that makes sure no action would destroy the links between tables
2- foreign key also acts as a constrain to stop invalid data from being inserted into the foreign key column, as it has to reference to the primary key column in the other table
code example in MySql:
CREATE TABLE Orders (
OrderID int NOT NULL,
OrderNumber int NOT NULL,
PersonID int,
PRIMARY KEY (OrderID),
FOREIGN KEY (Personal_id) REFERENCES Persons(Personal_id)
);
code example is SQL-Server/MS Access/ Oracle:
CREATE TABLE Orders (
OrderID int NOT NULL PRIMARY KEY,
OrderNumber int NOT NULL,
PersonID int FOREIGN KEY REFERENCES Persons(Personal_id)
);
Primary key of Orders table is the orderID.
Foreign key of Orders table is what links it to persons table.
Personal_id columns are the columns that link both tables.
Both of the code chunks do the same depends what are you working with.
real world example:
assuming:
customer_Table column to be a primary key in restaurant table and foreign key in orders table.
if a waiter is putting customer_Table number 20 in the machine, and he puts customer_Table 200 by mistake such key does not exist as a primary key in restaurant table so he cant.
Extra:
what if you want to allow naming of the FOREIGN KEY constraint, and define a FOREIGN KEY constraint on many columns?
MySQL / SQL Server / Oracle / MS Access:
CREATE TABLE Orders (
OrderID int NOT NULL,
OrderNumber int NOT NULL,
Personal_id int,
PRIMARY KEY (OrderID),
CONSTRAINT FK_PersonOrder FOREIGN KEY (Personal_id)
REFERENCES Persons(Personal_id)
);
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'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
I need to add a primary key on a table "usernames"
I have 3 columns in it :
userid int(10)
username char(20)
user char(50)
and the primary key is set on 'username' field and i used it as a foreign key to link it to another table. Now i need to add primary key on 'userid' field also... so i tried out :
alter table `usernames` drop primary key, add primary key(userid,username);
and i get an error saying
ERROR 1553 (HY000): Cannot drop index 'PRIMARY":needed in a foreign key constraint
is there any possible way to do this ??
There is:
Drop the FK constraint
Drop PK Constraint
Create New PK
Add Unique Constraint on the name column
Recreate FK
Raj
I assume you use MySql (despite you tag your question as Sql Server).
You can decide to:
Disable all check and try to remove primary key but the new must have the same name
or
Drop foreign key constraints referred to your primary key and then remove your primary key and finally re-add foreign keys
You have to drop the foreign key in order to modify the primary key
As implied by the name, a table can only have at most one PRIMARY key. Whilst it can have other UNIQUE keys, which have a similar effect, they really ought not be used for foreign-key relations.
So, you have two choices:
Retain your existing schema (perhaps username is a perfectly good natural key such that you need not bother with a synthetic one, in which case you can consider dropping the userid column altogether); or
Making userid your PRIMARY key, in which case username should not be used for foreign key relations. I outline below a method for doing this "offline" (where the database is guaranteed not to be altered by any other process during the transition); should you be working "online", you will need to add further steps to ensure integrity is preserved:
Add a new userid column for the foreign key in all child tables and drop the existing foreign key constraint:
ALTER TABLE foo
ADD COLUMN userid INT(10),
DROP FOREIGN KEY fk_name;
Change the primary key in your usernames tables (should you wish for the database to enforce a uniqueness constraint over username, you can define a UNIQUE key instead):
ALTER TABLE usernames
DROP PRIMARY KEY,
ADD PRIMARY KEY (userid),
ADD UNIQUE KEY (username); -- optional
Update the child tables to contain the relevant userid from the parent:
UPDATE foo JOIN usernames USING (username)
SET foo.userid = usernames.userid;
Add the new foreign key constraints and drop the old username columns from the child tables:
ALTER TABLE foo
ADD FOREIGN KEY (userid) REFERENCES usernames (userid),
DROP COLUMN username;