I'm trying to create a table with a recursive column, but It doesn't work. Later I tried it and it did work, but the I dropped the table because of a problem and now I don't know what I did.
The table's name is "security" and this is the script:
create table security (
id_emplo int(6) ZEROFILL NOT NULL,
id_boss varchar(10) DEFAULT NULL,
TIP int(5) NOT NULL,
security_division varchar(40),
PRIMARY KEY (id_emplo),
FOREIGN KEY (id_emplo) REFERENCES employees (id_emple) ON DELETE RESTRICT ON UPDATE CASCADE,
FOREIGN KEY (id_boss) REFERENCES security (id_emple) ON DELETE RESTRICT ON UPDATE CASCADE
) ENGINE=INNODB;
I have another table called "employees". If I try to create the table with only "id_emplo" REFERENCES employess... It doesn't have any problem.
You have to be very careful about types and declarations. The following should work:
create table security (
id_emplo int(6) ZEROFILL NOT NULL,
id_boss int(6) ZEROFILL DEFAULT NULL,
TIP int(5) NOT NULL,
security_division varchar(40),
PRIMARY KEY (id_emplo),
FOREIGN KEY (id_emplo) REFERENCES employees (id_emple) ON DELETE RESTRICT ON UPDATE CASCADE,
FOREIGN KEY (id_boss) REFERENCES security (id_emplo) ON DELETE RESTRICT ON UPDATE CASCADE
);
Here is the SQL Fiddle.
You had two main problems:
You had the name of the column incorrect. It should be id_emplo rather than id_emple (although I give foreign key columns the same name as the column they refer to when I can).
The types were incompatible.
Related
CREATE TABLE doctor(
Did varchar(30) not null,
spid int,
Hid int,
Dname varchar(200)not null,
Dnumber int,
fee decimal(10,2)not null,
constraint primary key(Did),
constraint unique(Did,Dname),
constraint foreign key(spid)references speciality(spid)
on delete cascade on update cascade,
constraint foreign key(Hid)references hospital(Hid)
on delete cascade on update cascade
)engine=innodb;
It's hard to give an answer without the error message or your version of mysql, but I'd recommend to be sure that spid column of speciality is also defined is int, not int(11) or unsigned int(and also for other foreign key references).
And also your primary key is already always unique, I don't see any point including that in another unique constraint.
I have 3 tables which are linked to each other
task
client
compliance
The relationship is as shown in diagram below
The compliance table has the foreign key as below
The task table has the foreign key as below
Issue:
When I edit/update clientno in client table, I get
1452: Cannot add or update a child row: a foreign key constraint fails
(`task`, CONSTRAINT `task_ibfk_1` FOREIGN KEY (`officeid`, `clientid`) REFERENCES `client` (`officeid`, `clientno`) ON UPDATE CASCADE)
I expected that when clientno was changed in client table, the same will be updated in both complaince and task table.
I guess I am hitting a known limitation of InnoDB engine. Which goes not allow cascading updates to FK. If this is true, then what is the solution to updating the 3 tables with new clientno?
EDIT 1: As pointed out by #pankaj, how to overcome
If ON UPDATE CASCADE recurses to update the same table it has previously updated during the cascade, it acts like RESTRICT. This means that you cannot use self-referential ON UPDATE CASCADE operations. This is to prevent infinite loops resulting from cascaded updates.
Edit 2:
create table client
(
officeid char(6) not null,
clientno char(10) not null,
fname varchar(40) not null,
primary key (officeid, clientno)
);
create index officeid_clientno
on client (officeid, clientno);
create table compliance
(
officeid char(6) not null,
id smallint(5) unsigned not null,
clientid char(10) not null,
primary key (officeid, id),
constraint compliance_ibfk_2
foreign key (officeid, clientid) references client (officeid, clientno)
on update cascade
on delete cascade
);
create index officeid_clientid
on compliance (officeid, clientid, id);
create table task
(
officeid char(6) not null,
taskno char(10) not null,
clientid char(10) not null,
taskname varchar(50) not null,
complianceid smallint(5) unsigned null,
primary key (officeid, taskno),
constraint task_ibfk_1
foreign key (officeid, clientid) references client (officeid, clientno)
on update cascade,
constraint task_ibfk_4
foreign key (officeid, clientid, complianceid) references compliance (officeid, clientid, id)
on update cascade
);
create index officeid_clientid_complianceid
on task (officeid, clientid, complianceid);
FYI: I tried in mariadb 10.3 as well as mysql 8.0
The problem is related to the way relationships are declared.
First of all, as commented by #Nick, there is no need for a relation between task and client, as this is already covered by the relation to compliance. Commenting the declaration of this superfluous constraint is enough the make the error disappear, as you can see in this db fiddle.
create table task
(
officeid char(6) not null,
...
primary key (officeid, taskno),
-- constraint task_ibfk_1
-- foreign key (officeid, clientid) references client (officeid, clientno)
-- on update cascade,
constraint task_ibfk_4
foreign key (officeid, clientid, complianceid) references compliance (officeid, clientid, id)
on update cascade
);
Another suggestion is to use an autoincremented primary key in all tables (you can use an UNIQUE index to enforce composite referential integrity rules). This is the most usual way to proceed with MySQL, with which handling relationships is pretty straighforward.
I think that your problem stems from using mutable fields as primary keys
You can mitigate this by using a surrogate immutable primary key and adding a unique key to your mutable fields. You should be able to apply the same constraints as before without compromising data integrity
For example:
CREATE TABLE client (
id INT(10) UNSIGNED NOT NULL AUTO-INCREMENT PRIMARY,
officeid CHAR(6) NOT NULL,
clientno CHAR(10) NOT NULL,
fname VARCHAR(40) NOT NULL
);
CREATE UNIQUE INDEX uq-client-officeid-clientno IN client (officeid, clientno);
CREATE TABLE compliance (
id SMALLINT(5) UNSIGNED NOT NULL AUTO-INCREMENT PRIMARY,
client_id INT(10) UNSIGNED NOT NULL,
CONSTRAINT fk-compliance-client-id FOREIGN KEY id
REFERENCES client (id)
);
CREATE INDEX ix-compliance-id-client_id IN compliance (id, client_id);
CREATE TABLE task (
id INT(10) UNSIGNED NOT NULL AUTO-INCREMENT PRIMARY,
client_id INT(10) UNSIGNED NOT NULL,
compliance_id SMALLINT(5) UNSIGNED NULL,
taskno CHAR(10) NOT NULL,
taskname VARCHAR(50) NOT NULL,
CONSTRAINT fk-task-client-id FOREIGN KEY id
REFERENCES client (id),
CONSTRAINT fk-task-compliance-id-client_id FOREIGN KEY (compliance_id, client_id)
REFERENCES compliance (id, client_id)
);
This table structure mimics your current constraints and will allow you to update a clientno without needing the cascades
Note the foreign key fk-task-compliance-id-client_id which makes sure the compliance referenced by a task contains the correct client_id
I would also consider a separate table, office, with a surrogate integer primary key and containing the character based officeid. This could then be reference by the client table
I'm having a problem creating a database in MySQL.
The error code:'Error code 1215: cannot add foreign key constraint' pops up when i try to implement my changes. I've paid attention to all the necessary things but i can't find the solution.
This error only happened after i added some tables after having made an initial database(which did work), so hopefully i'm not dealing with this problem throughout the whole project.
Here's a snippet of the code in which the error occurs, the foreign key that's not working correctly is 'tournament_id' referencing to 'id' in tournament:
CREATE DATABASE allin;
USE allin;
CREATE TABLE employee (
phone_number char(12) NOT NULL,
birth_date date NOT NULL,
tournament_id int NOT NULL AUTO_INCREMENT,
PRIMARY KEY(phone_number),
FOREIGN KEY(tournament_id) REFERENCES tournament(id) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Second table:
CREATE TABLE tournament (
id int NOT NULL AUTO_INCREMENT,
date date NOT NULL,
time time NOT NULL,
cost decimal(5,2) NOT NULL,
min_players int NOT NULL,
min_age int NOT NULL,
max_age int NOT NULL,
location_id int NULL,
winner_id int NULL,
type varchar(40) NULL,
PRIMARY KEY(id),
FOREIGN KEY(winner_id) REFERENCES player(id) ON DELETE SET NULL ON UPDATE CASCADE,
FOREIGN KEY(location_id) REFERENCES event_location(id) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
The issue is here:
FOREIGN KEY(tournament_id) REFERENCES tournament(id) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
the above query is of CREATE TABLE employee. In this query, you are creating a FOREIGN KEY that refers to tournament(id), but as of now there is no tournament table exist in the specified database as the tournament table create query is reside below in the sequence.
I layman terms we can say, you are trying to refer a table column that
do not exist.
So to resolve this, run all you parent table creation query first, and than child table.
tournament_id int NOT NULL AUTO_INCREMENT,
PRIMARY KEY(phone_number)
Hey, I don't think you could set another primary key while an "auto increment" already exist
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.
I have four entities:
person
center
activity
address
So my idea is:
A person may have an associated address.
A center may have an associated address.
An activity may have an associated address.
Is this mysql design correct for a joomla component?
CREATE TABLE `#__person` (
`id` int(10) NOT NULL AUTO_INCREMENT,
other fields...
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `#__center` (
`id` int(10) NOT NULL AUTO_INCREMENT,
other fields...
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `#__activity` (
`id` int(10) NOT NULL AUTO_INCREMENT,
other fields...
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `#__address` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`line1` varchar(30),
`line2` varchar(30),
`locality` varchar(10),
`region` varchar(10),
`country` varchar(10),
`postcode` varchar(10),
`person_id` int(10),
`center_id` int(10),
`activity_id` int(10),
PRIMARY KEY (id),
FOREIGN KEY `person_id` REFERENCES `#__person` (id) ON DELETE CASCADE,
FOREIGN KEY `center_id` REFERENCES `#__center` (id) ON DELETE CASCADE,
FOREIGN KEY `activity_id` REFERENCES `#__activity` (id) ON DELETE CASCADE,
other fields...
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
So i.e:
If I delete a person, automatically his/her corresponding address will be deleted?
And if I delete an address, what will happen to their references? (hope nothing)
What happens if the same address is an address for a center and for an activity?
Are the foreign keys in the correct table or should i put an address_id field in person,center and activity?
I'm a bit confused about my design.
Thank you for your suggestions.
Instead of placing an id for person, center and activity into the address table, I would suggest placing an address_id into each of the other tables (person, center, and activity). Then, you could reuse the same address across the other tables and in different combinations of person, center, and activity.
And about cascade, I think the MySQL Reference manual explains it well:
CASCADE: Delete or update the row from the parent table, and
automatically delete or update the matching rows in the child table.
Both ON DELETE CASCADE and ON UPDATE CASCADE are supported. Between
two tables, do not define several ON UPDATE CASCADE clauses that act
on the same column in the parent table or in the child table.
So if you did change address_id to be in each of the other tables and then you applied the foreign key constraint
FOREIGN KEY `address_id` REFERENCES `#__address` (id) ON DELETE CASCADE
then when you deleted the row in the address table (the one WITHOUT the foreign key constraint), the matching rows in either person, center, or activity (where the foreign keys are defined), would be deleted. BUT, I am guessing that this might not be what you want, because you said a person, center and activity "may" have an address. So if you deleted the address, you do not necessarily want to delete the person, center or activity that was using that address. If that is true, then I would change your foreign key constraint in each of the 3 tables to:
FOREIGN KEY `address_id` REFERENCES `#__address` (id) ON DELETE SET NULL