I'm trying to manage some internet logs. I'm essentially capturing what IPs are reaching out to what other IPs and making reports on it.
Problem is there's a ton of chatter and I'm not sure if I can make my schema any better.
my table schema:
CREATE TABLE `IpChatter` (
`Id` bigint(20) NOT NULL AUTO_INCREMENT,
`SourceIp` bigint(20) NULL,
`DestinationIp` bigint(20) NULL,
`SourcePort` int(11) NULL,
`DestinationPort` int(11) NULL,
`FKToSomeTableWithExtraMetaDataId` bigint(20) NOT NULL,
CONSTRAINT `PK_IpChatter` PRIMARY KEY (`Id` ASC)
) ENGINE=InnoDB;
CREATE INDEX `IX_IpChatter_FKToSomeTableWithExtraMetaDataId` ON `IpChatter` (`FKToSomeTableWithExtraMetaDataId`) using HASH;
CREATE INDEX `IX_IpChatter_Main_Query_SourceIp` ON `IpChatter` (`SourceIp`);
CREATE INDEX `IX_IpChatter_Main_Query_DestinationIp` ON `IpChatter` (`DestinationIp`);
CREATE INDEX `IX_IpChatter_Main_Query_SourcePort` ON `IpChatter` (`SourcePort`);
CREATE INDEX `IX_IpChatter_Main_Query_DestinationPort` ON `IpChatter` (`DestinationPort`);
ALTER TABLE `IpChatter` ADD CONSTRAINT `FK_IpChatter_FKToSomeTableWithExtraMetaData`
FOREIGN KEY (`FKToSomeTableWithExtraMetaDataId`) REFERENCES `FKToSomeTableWithExtraMetaData` (`Id`)
ON DELETE CASCADE;
Right now I've got 2mill rows of data and pulls back data I need in about 4sec. However this is from using relatively light testing data. I'd imagine the size of the data being 30X larger in the final product. So that 4 sec will surely mean 2mins in the final product. Is there a better way I could normalize this data or have I hit a bottle neck and there isn't much I can do? Also, Are the indexes I picked ok?
Never mind, I figured it out. I guess I just needed to type out the problem to help me think up a solution.
So after looking at my data I've noticed a lot of pairings are repeated but under a different FKToSomeTableWithExtraMetaDataId value.
So tells me I can normalize the data by creating a table with distinct pairings of SourceIp,DestinationIp,SourcePort,DestinationPort`. Then create a lookup table to join up that table with the ToSomeTableWithExtraMetaData table.
This reduces my raw IP data by 1700%! This will give a tremendous increase in performance when searching for a range of IPs and now it has to go though far less rows. Plus with the lookup table I have greater flexibility on how I can query.
CREATE TABLE `IpChatter` (
`Id` bigint(20) NOT NULL AUTO_INCREMENT,
`SourceIp` bigint(20) NULL,
`DestinationIp` bigint(20) NULL,
`SourcePort` int(11) NULL,
`DestinationPort` int(11) NULL,
`FKToSomeLookupTableId` bigint(20) NOT NULL,
CONSTRAINT `PK_IpChatter` PRIMARY KEY (`Id` ASC)
) ENGINE=InnoDB;
CREATE INDEX `IX_IpChatter_FKToSomeLookupTableId` ON `IpChatter` (`FKToSomeLookupTableId`) using HASH;
CREATE INDEX `IX_IpChatter_Main_Query_SourceIp` ON `IpChatter` (`SourceIp`);
CREATE INDEX `IX_IpChatter_Main_Query_DestinationIp` ON `IpChatter` (`DestinationIp`);
CREATE INDEX `IX_IpChatter_Main_Query_SourcePort` ON `IpChatter` (`SourcePort`);
CREATE INDEX `IX_IpChatter_Main_Query_DestinationPort` ON `IpChatter` (`DestinationPort`);
ALTER TABLE `IpChatter` ADD CONSTRAINT `FK_IpChatter_FKToSomeLookupTable`
FOREIGN KEY (`FKToSomeLookupTableId`) REFERENCES `FKToSomeLookupTable` (`Id`)
ON DELETE CASCADE;
CREATE TABLE `FKToSomeLookupTable` (
`FKToSomeTableWithExtraMetaDataId` bigint(20) NOT NULL,
`IpChatterId` bigint(20) NOT NULL,
CONSTRAINT `PK_FKToSomeLookupTable` PRIMARY KEY (`Id` ASC)
) ENGINE=InnoDB;
CREATE INDEX `IX_IpChatter_FKToSomeTableWithExtraMetaDataId` ON `FKToSomeLookupTable` (`FKToSomeTableWithExtraMetaDataId`) using HASH;
CREATE INDEX `IX_IpChatter_IpChatterId` ON `FKToSomeLookupTable` (`IpChatterId`) using HASH;
ALTER TABLE `FKToSomeLookupTable` ADD CONSTRAINT `FK_FKToSomeLookupTable_FKToSomeTableWithExtraMetaData`
FOREIGN KEY (`FKToSomeTableWithExtraMetaDataId`) REFERENCES `FKToSomeTableWithExtraMetaData` (`Id`)
ON DELETE CASCADE;
ALTER TABLE `FKToSomeLookupTable` ADD CONSTRAINT `FK_FKToSomeLookupTable_IpChatter`
FOREIGN KEY (`IpChatterId`) REFERENCES `IpChatter` (`Id`)
ON DELETE CASCADE;
Shrink the table size. Smaller is one way to help (some) with the speed.
IPv4 can be packed into INT UNSIGNED, which is 4 bytes versus your current 8-byte BIGINT. IPv6, on the other hand, needs BINARY(16); what you have will not work.
Port number, I think, will fit in a 2-byte SMALLINT UNSIGNED.
Are you expecting your tables to be bigger than 4 billion rows? If not, use INT UNSIGNED instead of BIGINT for ids.
Get rid of FOREIGN KEYs, they slow down things; meanwhile, the constraints have never triggered an error, have they? Do you really use the overhead of CASCADE?
Don't index every column. Look at your queries and index the columns or combinations of columns that would benefit SELECTs, UPDATEs, and DELETEs.
Please show the queries; without them, we cannot judge the performance.
Related
I have a table in database.
CREATE TABLE `comment_sheets` (
`id` mediumint(9) NOT NULL AUTO_INCREMENT,
`doc_id` mediumint(9) NOT NULL,
`level` varchar(10) DEFAULT NULL,
`author` varchar(30) DEFAULT NULL,
`status` varchar(10) DEFAULT NULL,
`creation_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `cs` (`doc_id`,`level`,`author`)
) ENGINE=InnoDB AUTO_INCREMENT=3961075 DEFAULT CHARSET=utf8 ;
My UNIQUE KEY cs (doc_id,level,author) is a problem now. I want to remove it, becouse i need duplicate values.
My question is. What should i have in my mind or what shoud I be worry about, when i want delete unique key?
Thanks.
To drop unique key
ALTER TABLE table_name
DROP INDEX index_name;
To drop primary key
ALTER TABLE table_name
DROP INDEX `PRIMARY`;
You need to alter table:
alter table comment_sheets drop INDEX `cs`
It really depends on how the key is used apart from enforcing uniqueness of data.
Check if the key is used in any foreign key relationships. If yes, you need to drop the foreign key before you can drop the unique one. (Well, mysql won't let you drop the index if the foreign key exits anyway)
Check what queries may make use of the key and how its removal would affect their performance. You may have to add a non-unique key on these fields back.
I this particular case dropping the index is relatively simple task because it is not the primary key, and it is not a fulltext index. The only thing that may take long is the removal of the index data if your table is big (judging from the auto increment value, it is not a small table)
I have some sport facilities that have fields that one can play 5x5 football in them. I am trying to make a simple reservation system for them.
My problem is that some fields combine and make bigger fields that the manages of the facilities want to treat them as their own entities (makes sense, if they book them like that why not).
Let's give an actual example.
We have facility FA. They have 3 5x5 fields one next to another, let's call then sa, sb, sc and any two of them can combine to make a 7x7 field, let's call it dd and all three to make a 10x10 field, let's call it te.
This happens with the other facilities as well but this is the more extreme case.
I have been trying to think how to model the tables for the fields when I make the reservation and deal with it but I am not sure.
One solution I have is to have a table for the fields
CREATE TABLE IF NOT EXISTS field (
id SMALLINT(5) UNSIGNED NOT NULL AUTO_INCREMENT,
arena_id SMALLINT(4) UNSIGNED NOT NULL,
internal_id TINYINT(3) UNSIGNED NOT NULL,
is_composite BOOLEAN NOT NULL DEFAULT FALSE,
PRIMARY KEY (id),
UNIQUE (arena_id, internal_id),
CONSTRAINT fk_field_arena_id FOREIGN KEY (arena_id) REFERENCES arena(id) ON UPDATE CASCADE ON DELETE CASCADE
)
;
And theh have a one to one or zero relationship with another table
CREATE TABLE IF NOT EXISTS field_component (
field_id SMALLINT(5) UNSIGNED NOT NULL,
component SMALLINT(5) UNSIGNED NOT NULL,
PRIMARY KEY (field_id, component),
CONSTRAINT fk_field_component_field_id FOREIGN KEY (field_id) REFERENCES field(id) ON UPDATE CASCADE ON DELETE CASCADE,
CONSTRAINT fk_field_component_field_id2 FOREIGN KEY (component) REFERENCES field(id) ON UPDATE CASCADE ON DELETE CASCADE
)
;
that will have entries with the fields that comprise a component field. An entry will exist here only when the flag is_composite in the field table is true.
A simpler solution I was thinking that is a bit more manual, was instead of having the second table and the flag, to just have a string column where I put the ids of the fields that make the composite field as a comma separated list.
On a separate note, I was thinking of moving the flag is composite to a third table called field_info that I might have one to one relationship with the field and will contain information about each field. i.e. size, material of the ground, if it's composite or not, notes about it etc.
Any thought suggestions, criticism, alternatives are welcome.
I would consider the following, that ensures in the composite table field_component that the child and composite arenas are at least the same. Note that InnoDB check constraints are not enforced.
Point #1: The is_composite quality in the following for the field_component implicitly pointing back to something that is truly a composite is not enforced. It could be with more compositing (meaning more tables).
Point #2: The datatypes should not be overly engineered into small and tiny INTs at this stage or perhaps ever. Especially if new to mysql.
Point #3: The FK relationships have the tendency to create KEYS for you automatically when not present in the child table. The unique key that we explicitly have in field_component effectly serves two purposes. It enforces non-dupes, and it serves as the index used where an FK auto-gen one would have been generated. Another one is generated automatically as can be seen in show create table. So, our UNIQUE KEY serves a few purposes there.
CREATE TABLE IF NOT EXISTS field (
id SMALLINT(5) UNSIGNED NOT NULL AUTO_INCREMENT,
arena_id SMALLINT(4) UNSIGNED NOT NULL,
internal_id TINYINT(3) UNSIGNED NOT NULL,
is_composite BOOLEAN NOT NULL DEFAULT FALSE,
PRIMARY KEY (id),
UNIQUE (arena_id, internal_id),
CONSTRAINT fk_field_arena_id FOREIGN KEY (arena_id) REFERENCES arena(id) ON UPDATE CASCADE ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS field_component (
field_id SMALLINT(5) UNSIGNED NOT NULL,
component SMALLINT(5) UNSIGNED NOT NULL,
PRIMARY KEY (field_id, component),
CONSTRAINT fk_field_component_field_id FOREIGN KEY (field_id) REFERENCES field(id) ON UPDATE CASCADE ON DELETE CASCADE,
CONSTRAINT fk_field_component_field_id2 FOREIGN KEY (component) REFERENCES field(id) ON UPDATE CASCADE ON DELETE CASCADE
);
TweakA:
CREATE SCHEMA TweakA;
USE TweakA;
-- drop table arena
CREATE TABLE IF NOT EXISTS arena
( id INT PRIMARY KEY,
aName varchar(200) NOT NULL
);
-- drop table field
CREATE TABLE IF NOT EXISTS field
( id INT AUTO_INCREMENT PRIMARY KEY,
arena_id INT NOT NULL, -- like the Arena #
internal_id INT NOT NULL, -- 1, 2, 3 for the field #
is_composite BOOLEAN NOT NULL DEFAULT FALSE,
friendly_name VARCHAR(100) NOT NULL,
UNIQUE KEY (arena_id, internal_id),
CONSTRAINT fk_field_arena_id FOREIGN KEY (arena_id) REFERENCES arena(id) ON UPDATE CASCADE ON DELETE CASCADE
);
-- drop table field_component
CREATE TABLE IF NOT EXISTS field_component
( id INT AUTO_INCREMENT PRIMARY KEY,
arena_id INT NOT NULL,
child_internal_id INT NOT NULL,
composite_internal_id INT NOT NULL,
-- The following UK will pick up part of what I will explain in the Narrative
UNIQUE KEY `unq_arena_comp_child` (arena_id,child_internal_id,composite_internal_id),
CONSTRAINT fk_field_child_field_id FOREIGN KEY (arena_id,child_internal_id)
REFERENCES field(arena_id, internal_id) ON UPDATE CASCADE ON DELETE CASCADE,
CONSTRAINT fk_field_composite_field_id FOREIGN KEY (arena_id,composite_internal_id)
REFERENCES field(arena_id, internal_id) ON UPDATE CASCADE ON DELETE CASCADE
-- note that InnoDB check constraints are not effective
);
-- Note, look at output from the following
-- show create table field_component; -- this shows the auto-gen of 1 key due to FK
--
-- The following block is a Helper block during testing
-- Truncate in reverse order:
-- TRUNCATE TABLE field_component;
-- TRUNCATE TABLE field;
-- TRUNCATE TABLE arena;
-- test data load:
INSERT arena(id,aName) VALUES (1,'Boston Arena, North Shore');
INSERT field(arena_id,internal_id,is_composite,friendly_name) VALUES
(1,1,FALSE,'sa'),
(1,2,FALSE,'sb'),
(1,3,FALSE,'sc'),
(1,4,TRUE,'dab'),
(1,5,TRUE,'dac'),
(1,6,TRUE,'dbc'),
(1,7,TRUE,'abc');
INSERT field_component(arena_id,child_internal_id,composite_internal_id) VALUES
(1,1,4),
(1,2,4),
(1,1,5),
(1,3,5),
(1,2,6),
(1,3,6),
(1,1,7),
(1,2,7),
(1,3,7); -- SUCCESS
INSERT field_component(arena_id,child_internal_id,composite_internal_id) VALUES
(2,2,4); -- will fail, as expected
INSERT field_component(arena_id,child_internal_id,composite_internal_id) VALUES
(1,72,4); -- will fail, as expected
INSERT field_component(arena_id,child_internal_id,composite_internal_id) VALUES
(1,1,444); -- will fail, as expected
show create table field_component;
-- the above will exhibit the AUTO_INCREMENT gap anomoly due to the above
-- expected failed inserts, setting AI=13 or so
DROP SCHEMA TweakA;
I wrote an FK Enforces Composite Relationship answer that got a little complicated. Yours can go that route depending on the level of DB Enforcement you are looking for.
Also see the MySQL Using FOREIGN KEY Constraints concerning auto-gen of KEYS due to FK relationships as mentioned in Point #3.
So, this answer could just keep growing as you work thru enforcement. Or do it client side. If it were me, I would do it DB Enforcement.
Regardless, as mentioned in comments, don't store CSV values in a column.
Hi i hope some one can help my problem is that when i try to add a foreign key constraint i get this error.
My database name is "hazard"
Child:
CREATE TABLE `child` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`a` INT(11) NULL DEFAULT NULL,
`b` INT(11) NULL DEFAULT NULL,
PRIMARY KEY (`id`)
)
COLLATE='utf8_general_ci'
Parent:
CREATE TABLE `parent` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`alfa` INT(11) NULL DEFAULT NULL,
`beta` INT(11) NULL DEFAULT NULL,
PRIMARY KEY (`id`)
)
COLLATE='utf8_general_ci'
Those are the create codes (using HeidiSQL)
and when i try to add a foreign key
with
ALTER TABLE CHILD MODIFY COLUMN A INT,add constraint fk_parent_child FOREIGN KEY(A) REFERENCES PARENT(ALFA);
or
ALTER TABLE CHILD add constraint fk1 foreign key (a) references parent(alfa);
I get the same error
Can't create table 'hazard.#sql-d04_53' (errno: 150)
this is happening to many of my classmates using MariaDB and mySQL
Beforehand an apology for the inconvenience and I hope you guys can help us.
Add
KEY (`alfa`)
to the parent table. "The referenced columns must be a PRIMARY KEY or a UNIQUE index." – https://mariadb.com/kb/en/mariadb/foreign-keys/
http://sqlfiddle.com/#!9/b4c12
Error 150 usually means you are updating the tables in the wrong order. That is, your first INSERT violates the FOREIGN KEY constraint that your second INSERT will fix.
In your case you are doing ALTER instead of INSERT. Swap the order of the ALTERs. If that does not work, check the data to see that you won't be violating FK constraints. If you get past that, read on...
In extreme cases, you can turn off foreign key constraints while doing the inserts, then turn them back on. (But that leaves you vulnerable to screw-ups.)
I have the following tables:
specie (MyIsam)
image (InnoDB)
specie_map (InnoDB)
The specie_map table should map an image to a specie, and therefore has the following columns:
specie_id
image_id
Both are int 11, just like the id columns of the specie and image tables. I know I can't create a foreign key between specie_id and specie=>id, since the specie table is a MyIsam table. However, I would expect it to be possible to create a foreign key between image_id and image=>id.
I can create that foreign key and it will save it, however, the CASCADE action I have associated with it does not work. When I delete an image, it does not delete the specie_map entry that is associated with it. I would expect this to work, as this foreign key is between InnoDB tables. Both columns are indexed and of the same data type.
Is this a limitation of MySQL, or am I doing something else wrong?
Update: as requested hereby the table definitions. I have snipped unimportant columns:
-- ----------------------------
-- Table structure for `image`
-- ----------------------------
DROP TABLE IF EXISTS `image`;
CREATE TABLE `image` (
`id` int(11) NOT NULL auto_increment,
`guid` char(36) default NULL,
`title` varchar(255) NOT NULL,
`description` text,
`user_id` int(11) NOT NULL,
`item_id` int(11) default NULL,
`date_uploaded` timestamp NOT NULL default '0000-00-00 00:00:00',
`date_created` timestamp NOT NULL default '0000-00-00 00:00:00',
`date_modified` timestamp NOT NULL default '0000-00-00 00:00:00',
`status` enum('softdeleted','tobedeleted','active') default 'active',
PRIMARY KEY (`id`),
KEY `image_user` (`user_id`),
KEY `image_item` (`item_id`),
KEY `image_mod_by` (`moderated_by`),
CONSTRAINT `image_mod_by` FOREIGN KEY (`moderated_by`) REFERENCES `user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `image_user` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='stores image data (not file data)';
-- ----------------------------
-- Table structure for `specie`
-- ----------------------------
DROP TABLE IF EXISTS `specie`;
CREATE TABLE `specie` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(256) NOT NULL,
`commonname` varchar(256) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=22 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
-- ----------------------------
-- Table structure for `specie_map`
-- ----------------------------
DROP TABLE IF EXISTS `specie_map`;
CREATE TABLE `specie_map` (
`id` int(11) NOT NULL auto_increment,
`image_id` int(11) NOT NULL,
`specie_id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`karma` int(11) NOT NULL,
`date_created` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `image_id` (`image_id`),
KEY `specie_id` (`specie_id`),
CONSTRAINT `specie_map_ibfk_1` FOREIGN KEY (`image_id`) REFERENCES `image` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Foreign keys works only with InnoDb in mysql. MyISAM doesn't support them (the statements are ignored).
And is there any reason why you mix multiple DB engines?
I think you should post the exact DDL statements you used when you attempted to create these tables and the foreign key. Foreign keys between innodb tables work fine, but there are still a few things to look out for:
0) Both tables must be InnoDB. This was already highlighted by the other posters and this is probably the immediate cause of your problem.
1) the data type of the referencing columns (those that make up the foreign key) and their respective referenced columns should be the same. For example, you can't create a foreign key constrain on an INT UNSIGNED column to a plain INT column.
2) if the foreign key is created as part of the table DDL, be sure to put the foreign key definition in the constraints section, that is, below all column definitions. For example:
CREATE TABLE parent (
id int unsigned PRIMARY KEY
);
CREATE TABLE child (
parent_id int unsigned
, foreign key (parent_id)
references parent (id)
);
will work but this:
CREATE TABLE child (
parent_id int unsigned
foreign key references parent (id)
);
won't. It will fail silently because MySQL's parser ignores these types of constraint definitions even before InnoDB gets to create the table (silly, but that's how it is)
3) There must be an index over all the referenced columns. Usually the referenced columns will together make up a primary key or a unique constraint anyway, but it is your job to define this before defining the foreign key.
Final word of advice: if you think your DDL is ok but you still get an error when you execute it, for example like this:
ERROR 1005 (HY000): Can't create table 'test.child' (errno: 150)
Warning (Code 150): Create table 'test/child' with foreign key constraint failed. There is no index in the referenced table where the referenced columns appear as the first columns.
Error (Code 1005): Can't create table 'test.child' (errno: 150)
Then these errors may still not reveal the true nature of the error (silly again, but that's how it is). To shed more light on it, run this command immediately after your attempt to create the foreign key:
SHOW ENGINE INNODB STATUS;
This will give you a bunch of status info, and one section there looks like this:
------------------------
LATEST FOREIGN KEY ERROR
------------------------
120122 11:38:28 Error in foreign key constraint of table test/child:
foreign key (parent_id) references parent (id) ):
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.5/en/innodb-foreign-key-constraints.html
for correct foreign key definition.
As you can see, this gives a bit more information and reveals the true problem, namely "column types in the table and the referenced table do not match for constraint"
So please, post your actual DDL, I'm sure there is a problem in there somewhere.
I am trying to design a database but I need some help with the relationships. Am i getting the table design right?
Here is the database idea..
User will submit a howto, each howto will have one or more steps associated with(a one to many). each step can have random pictures associated with(another one to many). so I am thinking of this:
CREATE TABLE `HowtoStepImage`
`id` int(10) unsigned NOT NULL auto_increment,
`user_id` int(10) unsigned NOT NULL,
`howto_id` varchar(25) NOT NULL,
`step_id` varchar(25) NOT NULL,
`img_id` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `hsi_k_1` (`howto_id`),
CONSTRAINT `hsi_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`),
CONSTRAINT `hsi_ibfk_2` FOREIGN KEY (`step_id`) REFERENCES `HowtoStep` (`step_id`),
CONSTRAINT `hsi_ibfk_3` FOREIGN KEY (`img_id`) REFERENCES `StepImage` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
table HowtoStep
step_id, title, content, created
primary key (step_id)
table StepImage
img_id, filename, created
CREATE TABLE `UserHowtoComment` (
`id` int(10) unsigned NOT NULL auto_increment,
`howto_id` varchar(25) NOT NULL,
`user_id` int(10) unsigned NOT NULL,
`comment` varchar(500) NOT NULL,
`created` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `UserHowtoComment_ibfk_1` (`howto_id`),
KEY `UserHowtoComment_ibfk_2` (`user_id`),
CONSTRAINT `UserHowtoComment_ibfk_1` FOREIGN KEY (`howto_id`) REFERENCES `HowtoStepImage` (`howto_id`),
CONSTRAINT `UserHowtoComment_ibfk_2` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
however, I am getting error when creating the table, I am sure it is due to my database design. here is what mysql>SHOW ENGINE INNODB STATUS; shows:
091217 9:59:59 Error in foreign key constraint of table UserhowtoComment:
FOREIGN KEY (`howto_id`) REFERENCES `howtoStepImage` (`howto_id`),
CONSTRAINT `UserHowtoComment_ibfk_2` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8:
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.0/en/innodb-foreign-key-constraints.html
for correct foreign key definition.
the howto_id is a key(index) in UserHowtoComment though. I am not sure if that is the exact problem here..
Make 3 tables: one for HowTo, one for HowToStep, one for HowToStepImage.
Give each table a clearly defined key, e.g. a number or a string.
Then let the 'child' table refer to the key of the parent table.
Make sure that the columns have clear names as well.
TABLE HowTo
COLUMNS HowToId(key)
TABLE HowToStep
COLUMNS HowToStepId(key), HowToId
TABLE HowToStepImage
COLUMNS HowToStepImageId(key), HowToStepId
your query is really messy e.g. step_id varchar(25) needs to be an int.
why dont you just use a gui programm or maybe the good old phpMyAdmin, so you can learn the from the Querys they are creating, phpMyAdmin also has a advanced feature call "Designer" to create constraints.
If I read this correctly, your HowToComment id is a foreign key to HowtoStepImage. Does every comment have to have an image? Seems like a chicken and the egg issue. It seems, from your problem description, that an image links to a comment, not the other way around.
you're falling prey to the misleading terminology in MySQL. in the relational model, key is (necessarily) distinct. in the MySQL-speak, it's just an index. you need either PRIMARY KEY or UNIQUE KEY.
edit to add explicitly what is implied above: foreign keys must point to a key in the relational sense.