How to create concatened primary key? - mysql

Hello I'm new to MySQL but I would like to create a unique ID based on two primary keys created in two other tables.
Here is just the part that interests us:
CREATE TABLE patient(
id_patient int NOT NULL AUTO_INCREMENT,
...,
PRIMARY KEY (id_patient))
CREATE TABLE surgeon(
id_surgeonint NOT NULL AUTO_INCREMENT,
...,
PRIMARY KEY (id_surgeon))
CREATE TABLE case(
id_patient int NOT NULL,
id_surgeon int NOT NULL,
CONSTRAINT FK_case_patient FOREIGN KEY (id_patient) REFERENCES patient(id_patient),
CONSTRAINT FK_case_surgeon FOREIGN KEY (id_surgeon) REFERENCES surgeon(id_surgeon),
CONSTRAINT id_case PRIMARY KEY (id_patient, `_`,id_surgeon));
I think i don't get the trick. I wanted the following result :
SELECT * FROM case;
id_case | id_patient | id_surgeon
32_56 | 32 | 56
18_66 | 18 | 66
I know that the speed of calculation will not be optimal but this id-case is really necessary and must be visible during the select

You can create a computed column, and if you really want its values on disk you can persist the computed column
CREATE TABLE case(
id_patient int NOT NULL,
id_surgeon int NOT NULL,
id_case varchar(30) AS CONCAT(id_patient, '_', id_surgeon),
CONSTRAINT FK_case_patient FOREIGN KEY (id_patient) REFERENCES patient(id_patient),
CONSTRAINT FK_case_surgeon FOREIGN KEY (id_surgeon) REFERENCES surgeon(id_surgeon),
CONSTRAINT pk_case PRIMARY KEY (id_patient,id_surgeon));
However unless you have the requirement that the pair (patient, surgeon) uniquely identifies a case you should consider adding in an extra field (e.g surgery date)

Related

Error Code 1215 Cannot Add Foreign Code Constraint

My code:
CREATE TABLE Horse (
ID SMALLINT UNSIGNED AUTO_INCREMENT,
RegisteredName VARCHAR(15),
PRIMARY KEY (ID)
);
CREATE TABLE Student (
ID SMALLINT UNSIGNED AUTO_INCREMENT,
FirstName VARCHAR(20),
LastName VARCHAR(30),
PRIMARY KEY (ID)
);
CREATE TABLE LessonSchedule (
HorseID SMALLINT UNSIGNED NOT NULL,
StudentID SMALLINT UNSIGNED NOT NULL,
LessonDateTime DATETIME NOT NULL,
Primary Key (HorseID, StudentID, LessonDateTime),
Foreign Key (HorseID) REFERENCES Horse(ID)
ON DELETE CASCADE,
Foreign Key (StudentID) REFERENCES Student(ID)
ON DELETE SET NULL
);
I'm trying to create "LessonSchedule" with these requirements:
HorseID - integer with range 0 to 65 thousand, not NULL, partial primary key, foreign key references Horse(ID)
StudentID - integer with range 0 to 65 thousand, foreign key references Student(ID)
LessonDateTime - date/time, not NULL, partial primary key
If a row is deleted from Horse, the rows with the same horse ID should be deleted from LessonSchedule automatically.
If a row is deleted from Student, the same student IDs should be set to NULL in LessonSchedule automatically.
The create horse table and create student table was given to me.
I am getting the error:
Query failed: ERROR 1215 (HY000) at line 15:
Cannot add foreign key constraint
I tested your table creation statements, and then ran SHOW ENGINE INNODB STATUS. This includes a section that gives more specific information about the reason for the failure.
------------------------
LATEST FOREIGN KEY ERROR
------------------------
2021-11-08 10:31:11 0x700002686000 Error in foreign key constraint of table test/lessonschedule:
Foreign Key (StudentID) REFERENCES Student(ID) ON DELETE SET NULL ):
You have defined a SET NULL condition though some of the
columns are defined as NOT NULL.
This means you can't define a foreign key with ON DELETE SET NULL if the column it is based on is defined with the NOT NULL option (as a PRIMARY KEY column must be).

Foreign key BIGSERIAL NULL Postgres

I can not insert a record in the POSTGRES database, I want the foreign key to be null.
My table:
CREATE TABLE sad_avaliado (
id BIGSERIAL NOT NULL,
tenant_id INT8 NOT NULL,
funcionario_id BIGSERIAL NOT NULL,
epoca_id BIGSERIAL NOT NULL,
cca_id BIGSERIAL,
avaliador_id BIGSERIAL NOT NULL,
apagado boolean NOT NULL,
PRIMARY KEY (id)
);
alter table sad_avaliado add constraint sad_funcionario_fkey foreign key (funcionario_id) references sad_funcionario;
alter table sad_avaliado add constraint sad_epoca_fkey foreign key (epoca_id) references sad_epoca;
alter table sad_avaliado add constraint sad_cca_fkey foreign key (cca_id) references sad_cca;
alter table sad_avaliado add constraint sad_avaliador_fkey foreign key (avaliador_id) references sad_avaliador;
My SQL Insert:
INSERT INTO public.sad_avaliado(
id, tenant_id, funcionario_id, epoca_id, cca_id, avaliador_id, apagado)
VALUES (1, 1, 1, 1, null, 1, false);
My Error:
ERROR: null value in column "cca_id" violates not-null constraint
The foreign key references for BIGSERIAL should use BIGINT:
CREATE TABLE sad_avaliado (
id BIGSERIAL NOT NULL,
tenant_id INT8 NOT NULL,
funcionario_id BIGINT NOT NULL,
epoca_id BIGINT NOT NULL,
cca_id BIGINT,
avaliador_id BIGINT NOT NULL,
apagado boolean NOT NULL,
PRIMARY KEY (id)
);
I think this is the one exception to the notion that foreign key references should have the same type as the primary key. I mean, the underlying type is the same, but BIGSERIAL is used to specify that it is auto-incrementing (other databases use a separate keyword such as auto_increment or identity).
bigserial is meant for autoincremented id columns and it has default "not null" and creates one sequence.
And you should not specify your id in insert statements as it is inserted as default with nextval()
see this example
test=# create table test01 ( id bigserial );
CREATE TABLE
test=# \d test01*
Table "public.test01"
Column | Type | Collation | Nullable | Default
--------+--------+-----------+----------+------------------------------------
id | bigint | | not null | nextval('test01_id_seq'::regclass)
Sequence "public.test01_id_seq"
Type | Start | Minimum | Maximum | Increment | Cycles? | Cache
--------+-------+---------+---------------------+-----------+---------+-------
bigint | 1 | 1 | 9223372036854775807 | 1 | no | 1
Owned by: public.test01.id
Use bigint instead of bigserial.

SQL - Only allow insert in one of three columns (one MUST be set though)

Lets say I have a table with these columns:
id | name | foo_id | bar_id | foobar_id
---------------------------------------
I want to make a constraint so at least one of the columns "foo_id", "bar_id" or "foobar_id" must be set.. However only one of these three must be set
Is that possible with an SQL constraint?
"name" (and any other possible columns) must be unaffected of the constraint
The problem is that your database is not properly designed. When a database isn't designed properly these are the kinds of problems that pop up. Here's how I would approach the design of these relationships:
CREATE TABLE Child (
child_id INT NOT NULL,
child_type INT NOT NULL, -- 1 = Foo, 2 = Bar, 3 = Foobar
CONSTRAINT PK_Child PRIMARY KEY CLUSTERED (child_id, child_type),
CONSTRAINT UI_Child_childid UNIQUE (child_id)
)
CREATE TABLE My_Table (
id INT NOT NULL,
name VARCHAR(20) NOT NULL,
child_id INT NOT NULL,
CONSTRAINT PK_My_Table PRIMARY KEY CLUSTERED (id),
CONSTRAINT FK_Child_MyTable FOREIGN KEY (child_id, child_type) REFERENCES Child (child_id, child_type)
)
CREATE TABLE Foo (
child_id INT NOT NULL,
child_type INT NOT NULL, -- Always = 1
some_foo_column VARCHAR(20) NOT NULL,
CONSTRAINT PK_Foo PRIMARY KEY CLUSTERED (child_id),
CONSTRAINT FK_Foo_Child FOREIGN KEY (child_id, child_type) REFERENCES Child (child_id, child_type)
)
CREATE TABLE Bar (
child_id INT NOT NULL,
child_type INT NOT NULL, -- Always = 2
some_bar_column VARCHAR(20) NOT NULL,
CONSTRAINT PK_Bar PRIMARY KEY CLUSTERED (child_id),
CONSTRAINT FK_Bar_Child FOREIGN KEY (child_id, child_type) REFERENCES Child (child_id, child_type)
)
CREATE TABLE Foo_Bar (
child_id INT NOT NULL,
child_type INT NOT NULL, -- Always = 3
some_foo_bar_column VARCHAR(20) NOT NULL,
CONSTRAINT PK_Foo_Bar PRIMARY KEY CLUSTERED (child_id),
CONSTRAINT FK_Foo_Bar_Child FOREIGN KEY (child_id, child_type) REFERENCES Child (child_id, child_type)
)
Of course, the Child table should be named something meaningful, not just "Child".
This enforces that My_Table can only have a single child_id and that it has to have at least one - in other words, exactly one.
By including the child_type as part of the primary key for the Child table and using it as part of the foreign key for all of the sub tables, you can enforce that each ID within the Child table only exists once in each sub table.
I primarily use MS SQL Server, so my apologies if some of this syntax isn't quite right for MySQL, but the idea is the important part and all of the pieces are possible in MySQL - it supports PKs, FKs, and unique constraints.

MySQL - Error Code 1215, cannot add foreign key constraint

i got these two succesfull queries:
create table Donors (
donor_id int not null auto_increment primary key,
gender varchar(1) not null,
date_of_birth date not null,
first_name varchar(20) not null,
middle_name varchar(20),
last_name varchar(30) not null,
home_phone tinyint(10),
work_phone tinyint(10),
cell_mobile_phone tinyint(10),
medical_condition text,
other_details text );
and
create table Donors_Medical_Condition (
donor_id int not null,
condition_code int not null,
seriousness text,
primary key(donor_id, condition_code),
foreign key(donor_id) references Donors(donor_id) );
but when i try this one:
create table Medical_Conditions (
condition_code int not null,
condition_name varchar(50) not null,
condition_description text,
other_details text,
primary key(condition_code),
foreign key(condition_code) references Donors_Medical_Condition(condition_code) );
i get "Error Code: 1215, cannot add foreign key constraint"
i dont know what am i doing wrong.
In MySql, a foreign key reference needs to reference to an index (including primary key), where the first part of the index matches the foreign key field. If you create an an index on condition_code or change the primary key st that condition_code is first you should be able to create the index.
To define a foreign key, the referenced parent field must have an index defined on it.
As per documentation on foreign key constraints:
REFERENCES tbl_name (index_col_name,...)
Define an INDEX on condition_code in parent table Donors_Medical_Condition and it should be working.
create table Donors_Medical_Condition (
donor_id int not null,
condition_code int not null,
seriousness text,
KEY ( condition_code ), -- <---- this is newly added index key
primary key(donor_id, condition_code),
foreign key(donor_id) references Donors(donor_id) );
But it seems you defined your tables order and references wrongly.
You should have defined foreign key in Donors_Medical_Condition table but not in Donors_Medical_Conditions table. The latter seems to be a parent.
Modify your script accordingly.
They should be written as:
-- create parent table first ( general practice )
create table Medical_Conditions (
condition_code int not null,
condition_name varchar(50) not null,
condition_description text,
other_details text,
primary key(condition_code)
);
-- child table of Medical_Conditions
create table Donors_Medical_Condition (
donor_id int not null,
condition_code int not null,
seriousness text,
primary key(donor_id, condition_code),
foreign key(donor_id) references Donors(donor_id),
foreign key(condition_code)
references Donors_Medical_Condition(condition_code)
);
Refer to:
MySQL Using FOREIGN KEY Constraints
[CONSTRAINT [symbol]] FOREIGN KEY
[index_name] (index_col_name, ...)
REFERENCES tbl_name (index_col_name,...)
[ON DELETE reference_option]
[ON UPDATE reference_option]
reference_option:
RESTRICT | CASCADE | SET NULL | NO ACTION
A workaround for those who need a quick how-to:
FYI: My issue was NOT caused by the inconsistency of the columns’ data types/sizes, collation or InnoDB storage engine.
How to:
Download a MySQL workbench and use it’s GUI to add foreign key. That’s it!
Why:
The error DOES have something to do with indexes. I learned this from the DML script automatically generated by the MySQL workbench. Which also helped me to rule out all those inconsistency possibilities.It applies to one of the conditions to which the foreign key definition subject. That is: “MySQL requires indexes on foreign keys and referenced keys so that foreign key checks can be fast and not require a table scan.” Here is the official statement: http://dev.mysql.com/doc/refman/5.7/en/create-table-foreign-keys.html
I did not get the idea of adding an index ON the foreign key column(in the child table), only paid attention to the referenced TO column(in the parent table).
Here is the auto-generated script(PHONE.PERSON_ID did not have index originally):
ALTER TABLE `netctoss`.`phone`
ADD INDEX `personfk_idx` (`PERSON_ID` ASC);
ALTER TABLE `netctoss`.`phone`
ADD CONSTRAINT `personfk`
FOREIGN KEY (`PERSON_ID`)
REFERENCES `netctoss`.`person` (`ID`)
ON DELETE NO ACTION
ON UPDATE NO ACTION;
I think you've got your tables a bit backwards. I'm assuming that Donors_Medical_Condtion links donors and medical conditions, so you want a foreign key for donors and conditions on that table.
UPDATED
Ok, you're also creating your tables in the wrong order. Here's the entire script:
create table Donors (
donor_id int not null auto_increment primary key,
gender varchar(1) not null,
date_of_birth date not null,
first_name varchar(20) not null,
middle_name varchar(20),
last_name varchar(30) not null,
home_phone tinyint(10),
work_phone tinyint(10),
cell_mobile_phone tinyint(10),
medical_condition text,
other_details text );
create table Medical_Conditions (
condition_code int not null,
condition_name varchar(50) not null,
condition_description text,
other_details text,
primary key(condition_code) );
create table Donors_Medical_Condition (
donor_id int not null,
condition_code int not null,
seriousness text,
primary key(donor_id, condition_code),
foreign key(donor_id) references Donors(donor_id),
foreign key(condition_code) references Medical_Conditions(condition_code) );
I got the same issue and as per given answers, I verified all datatype and reference but every time I recreate my tables I get this error. After spending couple of hours I came to know below command which gave me inside of error-
SHOW ENGINE INNODB STATUS;
LATEST FOREIGN KEY ERROR
------------------------
2015-05-16 00:55:24 12af3b000 Error in foreign key constraint of table letmecall/lmc_service_result_ext:
there is no index in referenced table which would contain
the columns as the first columns, or the data types in the
referenced table do not match the ones in table. Constraint:
,
CONSTRAINT "fk_SERVICE_RESULT_EXT_LMC_SERVICE_RESULT1" FOREIGN KEY ("FK_SERVICE_RESULT") REFERENCES "LMC_SERVICE_RESULT" ("SERVICE_RESULT") ON DELETE NO ACTION ON UPDATE NO ACTION
I removed all relation using mysql workbench but still I see same error. After spending few more minutes, I execute below statement to see all constraint available in DB-
select * from information_schema.table_constraints where
constraint_schema = 'XXXXX'
I was wondering that I have removed all relationship using mysql workbench but still that constraint was there. And the reason was that because this constraint was already created in db.
Since it was my test DB So I dropped DB and when I recreate all table along with this table then it worked. So solution was that this constraint must be deleted from DB before creating new tables.
Check that both fields are the same size and if the referenced field is unsigned then the referencing field should also be unsigned.

How do I ensure that a foreign key exists as a primary key in another table when data is inserted?

This is an example of some tables that I'm using.
create TABLE People(
peopleID int not null,
name varchar(40) not null,
primary key (peopleID)
);
create table car(
carID int not null,
peopleID int not null,
primary key (carID),
foreign key (peopleID) references People(peopleID)
);
How do I ensure that when I insert into 'car', the 'peopleID' foreign key exists as a primary key in the table 'People'.
For example, I would want the following statement to throw an error:
INSERT INTO car VALUES (123, 343);
... because 343 doesn't exist in 'PeopleID', as it is empty.
Thanks
This is a bit long for a comment.
You have described what the foreign key constraint does:
For storage engines supporting foreign keys, MySQL rejects any INSERT
or UPDATE operation that attempts to create a foreign key value in a
child table if there is no a matching candidate key value in the
parent table.
The constraint is described here.