MySQL Create Table Statement Strange Errors - mysql

I am trying to run some basic CREATE TABLE statements for my Databases course project and am getting some strange errors.
When I create the table Manuf it runs fine, but when I try to create the next table, Order, using the same syntax, it does not work.
Also, when I try to create this table, Items, I get an errno: 150. I believe this has to do with my foreign key creation, but I am not exactly sure. Here is a screenshot of that.
I am fairly new to using MySQL so any advice would be greatly appreciated, thank you.

The error on the Order table is caused by ORDER being a reserved word. You can specify it as `Order` with the backticks, but it's better if you choose a different name altogether.
The error 150 is related to the foreign key. The keys must be absolutely identical - the exact same definition, or the FK will fail with error 150.
Also, there must be an available index with that key definition or one compatible (see Kai Baku's example in the comment on the MySQL manual page). The same fields indexed in a different order will fail.
To begin with, check how those keys are defined in the origin tables. For example:
test1 varchar(50) not null
test2 varchar(50)
will not be compatible. I think that even a different collation is enough to throw FK off kilter (but this I haven't checked. The rest I'm sure of, from my personal bitter unexperience).
UPDATE: I forgot to mention, if you use InnoDB tables and issue the SHOW ENGINE INNODB STATUS, the blurb that comes out will contain a much better explanation of why the FK failed, somewhere about one third from top.

Related

Error when adding foreign key to newly created table (mySQL)

I am trying to alter table product to add a constraint of type foreign key for field petCat_ID so that it references table petCategory(ID). I just created table petCat_ID and i am getting a "Cannot add or update a child row" error.
This is the commands I performed to get this error:
Alter table product
-> ADD CONSTRAINT FK_petCatID
-> FOREIGN KEY (petCat_ID)
-> REFERENCES productCategory(ID);
Any help or tips would be greatly appreciated! Note: petCat_ID is in table product and productCategory is a different table.
In my comments I've mentioned that I need a clearer idea of what kind of database structure you have, but I have a series of things that will help you work through the problem you're having.
If an ALTER statement isn't working, and you have good syntax, it is because what you are doing conflicts with an already present rule.
Sometimes, doing a DROP TABLE command, followed by creating the table again can fix problems. This can be problematic if there are dependencies that keep you from dropping the table.
When things get dire, try looking at the script you used to make the DB in the first place. Modify it and see if you can get the properties you want. Once you do, make a new database table structure and migrate your table entries over to the new database from the old one.
I made a github repository here wherein I made a third normal form version of what the customer facing Amtrack database would look like, and even wrote scripts to add data to the tables, with examples. There are images showing the ER structure. I included my creation script, broken into each table's creation in specific order. It should be a good reference for how to assign table relationships, and that will give you a good idea of what you can alter. Disclaimer I wrote it for SSMS, but I don't believe I used anything SSMS specific I THINK that code should work in MySQL.

MySQL: Duplicate entry for key (Formerly "What does 'idx' mean?")

Update: After a lot of painful research, I've discovered what the problem actually is and updated the title to make a little more sense. I'll put my answer below.
Unfortunately, I'm not able to copy the query that's giving me this problem because it belongs to my company, so I'll have to keep my question very specific.
I have an INSERT INTO ... SELECT query that's returning this error:
Duplicate entry <gobbledygook> for key 'idx_<tablename>'
The tablename at the end is the correct name, but it has this weird idx_ prefix before it that's not a part of any of the tables I'm currently working with. What is that idx? Does it have something to do with the information_schema?
Update: Apparently, I need to clarify something: There is no column with idx in the name.
The numerous websearches didn't reveal much when I was trying to solve this problem, but I did finally figure it out (and JohnH's answer helped me to do this).
I finally discovered that "idx" is not something created by MySQL, but a name that someone else gave to the index. I have never come across a uniqueness constraint on an index that wasn't a key before, so I didn't know where that error came from.
This command showed all of the indices:
SHOW INDEX FROM <tablename>
And I was able to see that non-unique was set to 0 for this key.
To fix the problem, I was able to simply drop the index and recreate it, without adding a uniqueness constraint.
DROP INDEX idx_<tablename> ON <tablename>;
ALTER TABLE <tablename> ADD INDEX idx_<tablename> (<comma-separated columns>);
Whether or not removing the uniqueness constraint is a good idea remains to be seen, but it's also beyond the scope of this question.
"idx_" is a common prefix for index names.
You many have an index that does not allow duplicate values for the column values referenced by that index.
In my case the unique index had duplicate entries even though the column being indexed didn't. I can only think this was caused by a bug. Solution was
Stop the service that writes to the db
Drop the index
Recreate the index
(Do the operation that was previously failing)
Start the service
It's important if you are dropping an recreating an index that nothing can be given an opportunity to insert a duplicate entry while you are doing this. This is why I stopped the service that writes to the db.

Is there any disadvantages of unique column in MYSQL

i'd like to ask a question regarding Unique columns in MySQL.
Would like to ask experts on which is a better way to approach this problem, advantages or disadvantages if there is any.
Set a varchar column as unique
Do a SQL INSERT IGNORE
If affected rows > 0 proceed with running the code
versus
Leave a varchar column as not-unique
Do a search query to look for identical value
If there is no rows returned in query, Do a SQL INSERT
proceed with running the code
Neither of the 2 approaches is good.
You don't do INSERT IGNORE nor do you search. The searching part is also unreliable, because it fails at concurrency and compromises the integrity. Imagine this scenario: you and I try to insert the same info into the database. We connect at the same time. Code in question determines that there's no such record in the database, for both of us. We both insert the same data. Now your column isn't unique, therefore we'll end up with 2 records that are the same - your integrity now fails.
What you do is set the column to unique, insert and catch the exception in the language of your choice.
MySQL will fail in case of duplicate record, and any proper db driver for MySQL will interpret this as an exception.
Since you haven't mentioned what the language is, it's difficult to move forward with examples.
Defining a column as an unique index has a few advantages, first of all when you define it as an "unique index" MySQL can optimize your index for unique values (same as a primary key) because mysql doesn't have to check if there are more rows with the same value so it can use an optimized algoritme for the lookups.
Also you are assured that there never will be a double entry in your database instead of handeling this in multiple places in your code.
When you don't define it as UNIQUE you first need to check if an records exists in your table, and then insert something wich requires 2 queries (and even a full table lock) instead of 1 wich decreases your performance and is more error prone
http://dev.mysql.com/doc/refman/5.0/en/constraint-primary-key.html
I'm leaving the fact that you would use the INSERT IGNORE wich IGNORES the exception when the entry allready exists in the database (Still you could use it for high performance operations maybe in some sort of special case). A normal INSERT will give you the feedback if an entry allready exists
Putting a constraint like UNIQUE is better when it comes to query performance and data reliability. But there is also a trade-off when it comes to writing. So It's up to you which do you prefer. But in your case, since you also do INSERT IF NOT EXIST query, so I guess, it's better to just use the Constraint.

"Table already exists" when changing PK autoincrement in MySQL

I am quite new to MySQL and I have encountered a problem that I find quite puzzling. If I create a table with MySQL Workbench, when I set the PK I can choose it to auto-increment or not, as should be. However, if I change my mind later on, once the table has been created, I cannot alter the auto-increment flag any longer, as MySQL tells me that the "table already exists". That happens even if the table is empty.
The auto-generated SQL is as follows:
ALTER TABLE tablename
CHANGE COLUMN `ID` `ID` INT(11) NOT NULL AUTO_INCREMENT ;
and it fails with the error stated above. I have tried changing the algorithm and lock type, to no avail.
This does not happens in T-SQL or Oracle, for instance, so I fail to see a reason why it should fail in MySQL. Is there any way to fix this without having to drop and re-create the table?
Thanks.
From experience all the GUIs get a bit confused when you start changing primary keys, the number of error messages I've seen from SQL Server...
You don't need to drop the whole table, but it might be easiest to drop and then re-create the offending column.
Also, check out the MySQL dev docs, but I think either ALTER or MODIFY column are the two I'd go for and I'm not sure why the column name is there twice if you're not renaming it.
Ok, I discovered the culprit thanks to dbForge Studio. The same thing happens there, but this time the error is more explicit: I cannot change the auto-increment flag apparently because it is used as a foreign key on another table. I deleted the FK and then I was able to set the auto-increment.
Thank you all who helped me, I have learned some new things thanks to your comments.

Determine InnoDB FK Constraints without information_schema

I'm writing some code to inspect a MySQL database structure, and need information about Foreign Key constraints (on InnoDB tables).
There are two ways I know of to do this:
Parse the results of SHOW CREATE TABLE X
Use INFORMATION_SCEMA.REFERENTIAL_CONSTRAINTS
Unfortunately option two requires MySQL 5.1.16 or later, so I can't use it unless/until I can convince our server guy to update, And while I can probably get away with option 1, it feels messy and without writing a full SQL parser I wouldn't feel sure my code would always work with any table.
Is there another way of getting at this information?
Thanks
From the MySQL 5.0 manual online:
You can also display the foreign key constraints for a table like
this:
SHOW TABLE STATUS FROM db_name LIKE 'tbl_name';
The foreign key constraints are listed in the Comment column of the
output.
Poster indicates that this doesn't provide ON UPDATE and ON DELETE information which is an important part of foreign key behavior.
Another option:
Since you control the code involved, is it possible to set up another MySQL instance in the same environment which is version 5.1+? If so, let's call that instance dummy. Run the SHOW CREATE TABLE on the live database. Then, on dummy run a DROP TABLE IF EXIST followed by the output from the SHOW CREATE TABLE query.
Now you can use INFORMATION_SCHEMA on the dummy database to get the information.