I have a images table:
Images
image_id
image_type ('foo', 'bar')
type_id
How can I create a foreign key so if the image_type is foo, type_id should relate to foo table, if image_type is bar to bar table.
What you're trying to do is to create a supertype. In SQL this is best modeled like below (IMO at least). My apologies if the syntax isn't quite right for MySQL. I usually use MS SQL Server.
CREATE TABLE Image_Types (
image_type_id INT NOT NULL,
image_type CHAR(3) NOT NULL CONSTRAINT CHK_Image_Types_image_type CHECK (image_type IN ('Foo', 'Bar')),
CONSTRAINT PK_Image_Types PRIMARY KEY (image_type_id, image_type)
)
CREATE TABLE Foo (
image_type_id INT NOT NULL,
image_type CHAR(3) NOT NULL CONSTRAINT CHK_Foo_image_type CHECK (image_type IN ('Foo')),
some_foo_specific_column VARCHAR(100) NOT NULL,
CONSTRAINT PK_Foo PRIMARY KEY (image_type_id),
CONSTRAINT FK_Foo_ImageTypes FOREIGN KEY (image_type_id, image_type) REFERENCES Image_Types (image_type_id, image_type)
)
CREATE TABLE Bar (
image_type_id INT NOT NULL,
image_type CHAR(3) NOT NULL CONSTRAINT CHK_Bar_image_type CHECK (image_type IN ('Bar')),
some_bar_specific_column VARCHAR(100) NOT NULL,
CONSTRAINT PK_Bar PRIMARY KEY (image_type_id),
CONSTRAINT FK_Bar_ImageTypes FOREIGN KEY (image_type_id, image_type) REFERENCES Image_Types (image_type_id, image_type)
)
CREATE TABLE Images (
image_id INT NOT NULL,
image_type CHAR(3) NOT NULL CONSTRAINT CHK_Images_image_type CHECK (image_type IN ('Foo', 'Bar')),
image_type_id INT NOT NULL,
CONSTRAINT PK_Images PRIMARY KEY (image_id),
CONSTRAINT FK_Images_ImageTypes FOREIGN KEY (image_type_id, image_type) REFERENCES Image_Types (image_type_id, image_type)
)
An alternative approach, if your RDBMS supports it, is to use filtered indexed views on Image_Types and then have your FKs in Foo and Bar point at those views. That allows you to eliminate the image_type column from some of your tables. Some people prefer the above pattern even when filtered indexed views are available though.
Related
I am facing an error when creating a table between the following two statement
CREATE TABLE SECTION (
cid varchar(10) not null,
sno varchar(3) not null,
primary key (cid, sno),
foreign key (cid) references COURSE (cid)
);
CREATE TABLE ROUND_RELEASE (
cid varchar(10) not null,
sno varchar(3) not null,
rid int not null,
foreign key (cid) references SECTION (cid),
foreign key (sno) references SECTION (sno),
foreign key (rid) references ROUND (rid)
);
Error Code: 1822. Failed to add the foreign key constraint. Missing index for constraint 'round_release_ibfk_2' in the referenced table 'section'
However, when I try to swap the primary key order in SECTION table, I am able to create both table without error
CREATE TABLE SECTION (
cid varchar(10) not null,
sno varchar(3) not null,
primary key (**sno, cid**),
foreign key (cid) references COURSE (cid)
);
CREATE TABLE ROUND_RELEASE (
cid varchar(10) not null,
sno varchar(3) not null,
rid int not null,
foreign key (cid) references SECTION (cid),
foreign key (sno) references SECTION (sno),
foreign key (rid) references ROUND (rid)
);
The follow code above works, and I only swap the attribute, from my knowledge, the order does not matter, thus I am quite puzzled by why is this occurring.
Any guidance on this? Thanks!
Based on the error message, I assume that you are using MySQL.
What you are seeing is a documented behavior:
In the referenced table, there must be an index where the referenced columns are the first columns in the same order.
Let me pinpoint, however, that your code probably does not do what you really want. You probably should be creating a compound foreign key, that references the tuples of columns, rather than one foreign key per column:
create table round_release (
cid varchar(10) not null,
sno varchar(3) not null,
rid int not null,
foreign key (cid, sno) references section(cid, sno),
foreign key (rid) references round(rid)
);
One last thing to note is that your round_release table has no primary key defined; this is not a good practice, and might hurt you in several ways in the future. So, do create a primary key for the table, either as a separate column (possibly auto-incremented), or as a combination of existing columns.
I am creating some new tables and i want tot populate them with data for tests and i got into this problem with mysql 8.
I always worked with null FK on tables but now i don't know what is happening.
I think is something from mysql 8, i updated recently and i didn't have problems with it till now.
I am using 8.0.12.
error that i get is :
[23000][1452] Cannot add or update a child row: a foreign key
constraint fails (i2cwac_test.site_board_pins, CONSTRAINT
site_board_pins_sensor_types_id_fk FOREIGN KEY (id) REFERENCES
sensor_types (id))
table creation script:
CREATE TABLE site_board_pins
(
id bigint(20) PRIMARY KEY NOT NULL AUTO_INCREMENT,
site_board_id bigint(20) NOT NULL,
e_board_pin_id bigint(20) NOT NULL,
pin_type_id bigint(20) NOT NULL,
pin_operation_mode bigint(20) NULL,
sensor_type_id bigint(20) NULL,
enabled bit(1) NOT NULL ,
description varchar(500),
CONSTRAINT site_board_pins_site_boards_id_fk FOREIGN KEY (id) REFERENCES site_boards (id),
CONSTRAINT site_board_pins_e_board_pins_id_fk FOREIGN KEY (id) REFERENCES e_board_pins (id),
CONSTRAINT site_board_pins_pin_types_id_fk FOREIGN KEY (id) REFERENCES pin_types (id),
CONSTRAINT site_board_pins_pin_operation_mode_id_fk FOREIGN KEY (id) REFERENCES pin_operation_mode (id),
CONSTRAINT site_board_pins_sensor_types_id_fk FOREIGN KEY (id) REFERENCES sensor_types (id)
);
insert that fails :
INSERT INTO `site_board_pins` (`site_board_id`, `e_board_pin_id`, `pin_type_id`, `pin_operation_mode`, `sensor_type_id`, `enabled`)
VALUES
((select id from e_boards where name = 'Iboard Pro 1.1'),
(select ep.id from e_boards eb join e_board_pins ep on ep.e_board_id = eb.id where eb.name = 'Iboard Pro 1.1' and ep.name = 'A1'),
(select id from pin_types where mode = 'Analog'),
NULL,
NULL,
0);
Thanks in advance
Looks like you've messed up your FK definitions - all the FKs are declared say that your Id column exists in all these other tables.
For example, I'm pretty sure your first one is meant to be:
CONSTRAINT site_board_pins_site_boards_id_fk FOREIGN KEY (site_board_id) REFERENCES site_boards (id)
I'm trying to make a many-to-many relationship between two tables In Mysql WorkBench, and one of those 2 tables has a composite primary key ( parts are coming from 2 foreign keys). When I'm trying to generate the SQL I'm getting this error :
ERROR: Error 1215: Cannot add foreign key constraint
SQL Code:
-- -----------------------------------------------------
-- Table `A_D_schema`.`Resources_has_OwnerGroups`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `A_D_schema`.`Resources_has_OwnerGroups` (
`Resources_id` INT NOT NULL,
`OwnerGroups_id` INT NOT NULL,
`OwnerGroups_Instances_has_Customers_Instances_idInstances` INT NOT NULL,
`OwnerGroups_Instances_has_Customers_Customers_idCustomers` INT NOT NULL,
PRIMARY KEY (`Resources_id`, `OwnerGroups_id`, `OwnerGroups_Instances_has_Customers_Instances_idInstances`, `OwnerGroups_Instances_has_Customers_Customers_idCustomers`),
INDEX `fk_Resources_has_OwnerGroups_OwnerGroups1_idx` (`OwnerGroups_id` ASC, `OwnerGroups_Instances_has_Customers_Instances_idInstances` ASC, `OwnerGroups_Instances_has_Customers_Customers_idCustomers` ASC),
INDEX `fk_Resources_has_OwnerGroups_Resources1_idx` (`Resources_id` ASC),
CONSTRAINT `fk_Resources_has_OwnerGroups_Resources1`
FOREIGN KEY (`Resources_id`)
REFERENCES `A_D_schema`.`Resources` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_Resources_has_OwnerGroups_OwnerGroups1`
FOREIGN KEY (`OwnerGroups_id` , `OwnerGroups_Instances_has_Customers_Instances_idInstances` , `OwnerGroups_Instances_has_Customers_Customers_idCustomers`)
REFERENCES `A_D_schema`.`OwnerGroups` (`id` , `Instances_has_Customers_Instances_idInstances` , `Instances_has_Customers_Customers_idCustomers`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB
From the SHOW ENGINE INNODB STATUS I can see this message :
Cannot resolve column name close to:
)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_Resources_has_OwnerGroups_OwnerGroups1`
FOREIGN KEY (`OwnerGroups_id` , `OwnerGroups_Instances_has_Customers_Instances_idInstances` , `OwnerGroups_Instances_has_Customers_Customers_idCustomers`)
REFERENCES `A_D_schema`.`OwnerGroups` (`id` , `Instances_has_Customers_Instances_idInstances` , `Instances_has_Customers_Customers_idCustomers`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB
The SHOW CREATE TABLE Resources and SHOW CREATE TABLE OwnerGroups :
CREATE TABLE `Resources` (
`idResources` int(11) NOT NULL AUTO_INCREMENT,
`email` varchar(45) DEFAULT NULL,
`role` int(11) DEFAULT NULL COMMENT 'role : 1 disptcher \n0 admin',
PRIMARY KEY (`idResources`),
UNIQUE KEY `idresources_UNIQUE` (`idResources`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `OwnerGroups` (
`idOwnerGroups` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(45) DEFAULT NULL,
`group` int(11) DEFAULT NULL,
PRIMARY KEY (`idOwnerGroups`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CONSTRAINT `fk_Resources_has_OwnerGroups_Resources1`
FOREIGN KEY (`Resources_id`)
REFERENCES `A_D_schema`.`Resources` (`id`)
Your Resources table doesn't have a column id. Its primary key is idResources.
CONSTRAINT `fk_Resources_has_OwnerGroups_OwnerGroups1`
FOREIGN KEY (`OwnerGroups_id` , `OwnerGroups_Instances_has_Customers_Instances_idInstances` , `OwnerGroups_Instances_has_Customers_Customers_idCustomers`)
REFERENCES `A_D_schema`.`OwnerGroups` (`id` , `Instances_has_Customers_Instances_idInstances` , `Instances_has_Customers_Customers_idCustomers`)
Your OwnerGroups table doesn't have a column id. Its primary key is idOwnerGroups. It doesn't have the other two columns you reference at all.
In general, when you declare a foreign key, first you name the columns in the child table:
CREATE TABLE Child (
childCol1 INT,
childCol2 INT,
...
FOREIGN KEY (childCol1, childCol2) ...
Then you reference columns in the parent table:
... REFERENCES Parent (parentCol1, parentCol2)
);
You must use the names of columns as they exist in the parent table.
The columns you reference in the parent table must together be the PRIMARY KEY or UNIQUE KEY of that table. In other words, given the example above, it would not work against this Parent table:
CREATE TABLE Parent (
parentCol1 INT,
parentCol2 INT,
PRIMARY KEY (parentCol1)
);
Because the PRIMARY KEY does not include parentCol2.
In your case, the following should work:
CREATE TABLE IF NOT EXISTS `A_D_schema`.`Resources_has_OwnerGroups` (
`Resources_id` INT NOT NULL,
`OwnerGroups_id` INT NOT NULL,
`OwnerGroups_Instances_has_Customers_Instances_idInstances` INT NOT NULL,
`OwnerGroups_Instances_has_Customers_Customers_idCustomers` INT NOT NULL,
PRIMARY KEY (`Resources_id`, `OwnerGroups_id`, `OwnerGroups_Instances_has_Customers_Instances_idInstances`, `OwnerGroups_Instances_has_Customers_Customers_idCustomers`),
CONSTRAINT `fk_Resources_has_OwnerGroups_Resources1`
FOREIGN KEY (`Resources_id`)
REFERENCES `A_D_schema`.`Resources` (`idResources`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_Resources_has_OwnerGroups_OwnerGroups1`
FOREIGN KEY (`OwnerGroups_id`)
REFERENCES `A_D_schema`.`OwnerGroups` (`idOwnerGroups`)
ON DELETE NO ACTION
ON UPDATE NO ACTION
) ENGINE = InnoDB
I took out a couple of INDEX definitions that are redundant. You don't need to index your PRIMARY KEY, it's already the clustered index of the table. You don't need to index the column you use in a foreign key declaration, MySQL will index that column automatically if it need to (though if an index already exists for that column, the FK constraint will use that index).
I'm not sure I understand what your other two columns OwnerGroups_Instances_has_Customers_Instances_idInstances and OwnerGroups_Instances_has_Customers_Customers_idCustomers are meant to do. Typically in a many-to-many table, you only need enough columns to reference the primary keys of the respective parent tables.
Re your comment:
You should try refreshing the view of the schema from time to time. There's a button with a pair of curvy arrows, to the right of "SCHEMAS".
I am trying to create two column with same foreign key . This is Error in Mysql.
ERROR
errno: 150 “Foreign key constraint is incorrectly formed”
SCRIPT
CREATE TABLE IF NOT EXISTS `invictus`.`Votaciones` (
`idVotaciones` INT NOT NULL AUTO_INCREMENT,
`mvp` INT NOT NULL,
`idPartido-Jugador` INT NOT NULL,
`votante` INT NOT NULL,
PRIMARY KEY (`idVotaciones`),
INDEX `fk_Votaciones_Partido-Jugadores_idx` (`mvp` ASC, `idPartido-Jugador` ASC, `votante` ASC),
CONSTRAINT `fk_Votaciones_Partido-Jugadores`
FOREIGN KEY (`mvp` , `idPartido-Jugador` , `votante`)
REFERENCES `invictus`.`Partido-Jugadores` (`Jugador_idJugador` , `Equipos_Partido_idPartido` , `Jugador_idJugador`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
EDIT 1
Here the table Partido-Jugadores , where I want to reference my two colums with Jugador_idJugador
CREATE TABLE IF NOT EXISTS `invictus`.`Partido-Jugadores` (
`idPartido-Jugadores` INT NOT NULL AUTO_INCREMENT,
`Equipos_idEquipos` INT NOT NULL,
`Equipos_Partido_idPartido` INT NOT NULL,
`Equipos_Partido_fecha` DATETIME NOT NULL,
`Equipos_Partido_Grupo_idGrupo` INT NOT NULL,
`Equipos_nombreEquipo` VARCHAR(45) NOT NULL,
`Jugador_idJugador` INT NOT NULL,
PRIMARY KEY (`idPartido-Jugadores`, `Equipos_idEquipos`, `Equipos_Partido_idPartido`, `Equipos_Partido_fecha`, `Equipos_Partido_Grupo_idGrupo`, `Equipos_nombreEquipo`, `Jugador_idJugador`),
INDEX `fk_Partido-Jugadores_Equipos1_idx` (`Equipos_idEquipos` ASC, `Equipos_Partido_idPartido` ASC, `Equipos_Partido_fecha` ASC, `Equipos_Partido_Grupo_idGrupo` ASC, `Equipos_nombreEquipo` ASC),
INDEX `fk_Partido-Jugadores_Jugador1_idx` (`Jugador_idJugador` ASC),
CONSTRAINT `fk_Partido-Jugadores_Equipos1`
FOREIGN KEY (`Equipos_idEquipos` , `Equipos_Partido_idPartido` , `Equipos_Partido_fecha` , `Equipos_Partido_Grupo_idGrupo` , `Equipos_nombreEquipo`)
REFERENCES `invictus`.`Equipos` (`idEquipos` , `Partido_idPartido` , `Partido_fecha` , `Partido_Grupo_idGrupo` , `nombreEquipo`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_Partido-Jugadores_Jugador1`
FOREIGN KEY (`Jugador_idJugador`)
REFERENCES `invictus`.`Miembros-Grupo` (`Jugador_idJugador`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
What is the problem?
Thanks !
If you want the correct syntax, you will need to show what the primary key for Partido-Jugadores looks like.
However, you have repeated a column twice in the foreign key reference:
REFERENCES `invictus`.`Partido-Jugadores` (**`Jugador_idJugador`**, `Equipos_Partido_idPartido` , **`Jugador_idJugador`**)
I've never tried this, but I assume that it is an error in the definition of the primary key, and an error in the foreign key reference. Use the appropriate primary key definition.
EDIT:
If you have an auto-increment column in Partido-Jugadores, then that should be the primary key. That alone with nothing else:
PRIMARY KEY (`idPartido-Jugadores`),
Then the foreign key reference would be:
CONSTRAINT `fk_Votaciones_Partido-Jugadores`
FOREIGN KEY (`idPartido-Jugador)
REFERENCES `invictus`.`Partido-Jugadores` (`Jugador_idJugadores`)
ON DELETE NO ACTION ON UPDATE NO ACTION
Notes:
You should name the primary key in the singular, in my opinion.
You should not use - in table or column names. Use _ as a separator instead. That way, identifiers do not need to be escaped.
I am stuck with this error no 150 problem in mysql and I know there have been questions
which discuss this problem but I still can't find where I am wrong. Here is the database I am trying to create:
create table business (
ident varchar(40) NOT NULL,
name varchar(50) NOT NULL,
rating INT UNSIGNED NOT NULL,
PRIMARY KEY(ident)
) ENGINE=InnoDB;
create table deals (
business_id varchar(40) NOT NULL,
deals_id varchar(20) NOT NULL,
deals_title varchar(50) NOT NULL,
PRIMARY KEY (business_id, deals_id),
FOREIGN KEY (business_id) REFERENCES business(ident) ON DELETE CASCADE
) ENGINE=InnoDB;
create table d_options (
business_id varchar(40) NOT NULL,
dealid varchar(20) NOT NULL,
option_title varchar(40) NOT NULL,
PRIMARY KEY(business_id, dealid, option_title),
FOREIGN KEY(business_id) REFERENCES business(ident) ON DELETE CASCADE,
FOREIGN KEY(dealid) REFERENCES deals(deals_id)
) ENGINE=InnoDB;
I get error: ERROR 1005 (HY000): Can't create table 'test.d_options' (errno: 150)
I know for foreign key constraints to be satisfied there should be a index in the parent table as per mysql documentation, but I think that there is by default indexing
on primary key.
The result of innodb status is:
120530 0:47:48 Error in foreign key constraint of table test/d_options:
FOREIGN KEY(dealid) REFERENCES deals(deals_id)
) ENGINE=InnoDB:
Cannot find an index in the referenced table where the
referenced columns appear as the first columns, or column types
in the table and the referenced table do not match for constraint.
Note that the internal storage type of ENUM and SET changed in
tables created with >= InnoDB-4.1.12, and such columns in old tables
cannot be referenced by such columns in new tables.
See http://dev.mysql.com/doc/refman/5.1/en/innodb-foreign-key-constraints.html
for correct foreign key definition.
Any help is appriciated.
You have a compound primary key on (business_id, deal_id) and they are indexed as a pair, but to satisfy the FK, you need another index on deal_id alone:
create table deals (
business_id varchar(40) NOT NULL,
deals_id varchar(20) NOT NULL,
deals_title varchar(50) NOT NULL,
PRIMARY KEY (business_id, deals_id),
FOREIGN KEY (business_id) REFERENCES business(ident) ON DELETE CASCADE,
/* Add an index on deals_id, separate from the compound PK */
INDEX idx_deals_id (deals_id)
) ENGINE=InnoDB;