I have two tables as follow:
1st Table:
CREATE TABLE User (
User_ID VARCHAR(8)NOT NULL PRIMARY KEY,
User_Name VARCHAR (25) NOT NULL,
User_Gender CHAR (1) NOT NULL,
User_Position VARCHAR (10) NOT NULL,
);
2nd table:
CREATE TABLE Training (
Training_Code VARCHAR(8) NOT NULL Primary Key,
Training_Title VARCHAR(30) NOT NULL,
);
I am trying to create a table which has two foreign keys to join both of the previous tables:
CREATE TABLE Request (
User_ID VARCHAR(8) NOT NULL,
Training_Code VARCHAR(8) NOT NULL,
Request_Status INT(1) NOT NULL
);
When I am trying to set the foreign keys in the new table, the User_ID can be done successfully but the Training_Code cannot be set to foreign key due to the error:
ERROR 1215 (HY000): Cannot add foreign key constraint
As I searched for this problem, the reason for it, is that data type is not the same, or name is not the same.. but in my situation both are correct so could you tell me what is wrong here ?
You need an index for this column in table Request too:
Issue first
CREATE INDEX idx_training_code ON Request (Training_Code);
Then you should be successful creating the foreign key constraint with
ALTER TABLE Request
ADD CONSTRAINT FOREIGN KEY idx_training_code (Training_Code)
REFERENCES Training(Training_Code);
It worked for me. But I've got to say that it worked without create index too, as the documentation of Using FOREIGN KEY Constraints states:
MySQL requires indexes on foreign keys and referenced keys so that
foreign key checks can be fast and not require a table scan. In the
referencing table, there must be an index where the foreign key
columns are listed as the first columns in the same order. Such an
index is created on the referencing table automatically if it does not
exist. This index might be silently dropped later, if you create
another index that can be used to enforce the foreign key constraint.
index_name, if given, is used as described previously.
Emphasis by me. I don't know what's the issue in your case.
Demo
Explanation of the issue
The behavior mentioned in the question can be reproduced if the table Training is using the MyISAM storage engine. Then creating a foreign key referencing the table Training will produce the mentioned error.
If there's data in the table, then simple dropping of the table would not be the best solution. You can change the storage engine to InnoDB with
ALTER TABLE Training Engine=InnoDB;
Now you can successfully add the foreign key constraint.
Related
I'm creating tables in MariaDB 10.6 database for TPC-H benchmark.
CREATE TABLE works ok, but adding FOREIGN KEY fails.
I tried following mariadbtutorial and documentation but this doesn't work too.
I suspect:
syntax of FOREIGN KEY is wrong
Wrong datatype in column that reference foreign key.
column refering to foreign key should be index
there's something wrong with data generated by dbgen from TPC-H benchmark.
The errors that occured:
warning 150: alter table bazatest2.nation with foreign key (N_REGIONKEY) constraint failed. field type or character set for column 'N_REGIONKEY' does not match referenced column 'R_REGIONKEY'.
Tried changing BIGINT NOT NULL to BIGINT UNSIGNED NOT NULL
but different error occurs:
error 1452 when i tried adding UNSIGNED to BIGINT in column that should refer to foreign key.
Part of file containing creates:
DROP TABLE IF EXISTS NATION CASCADE;
CREATE TABLE NATION (
N_NATIONKEY SERIAL PRIMARY KEY,
N_NAME CHAR(25),
N_REGIONKEY BIGINT UNSIGNED NOT NULL, -- references R_REGIONKEY
N_COMMENT VARCHAR(152)
);
DROP TABLE IF EXISTS REGION CASCADE;
CREATE TABLE REGION (
R_REGIONKEY SERIAL PRIMARY KEY,
R_NAME CHAR(25),
R_COMMENT VARCHAR(152)
);
Part of file with foreign key constraints:
ALTER TABLE NATION ADD CONSTRAINT FOREIGN KEY (N_REGIONKEY) REFERENCES REGION(R_REGIONKEY);
I tried solving this by changing syntax of alter table add constraint foreign key and searching for solutions all yesterday and haven't found solution.
Most likely is that column referencing to foreign key should be index, or multiple errors,
but I don't know what should i change in my code.
Thanks for all answers,
I added UNSIGNED to BIGINT, but it wasn't main source of my problem.
The problem was that I imported data from file where primary key values started at 0.
Here I found that in MariaDB/MySQL if 0 is given for primary key, it will automatically assign first value. It changed
0, 1, 2 to 1, 1, 2 and error occured.
There are two options:
changing settings of dbgen (program generating data for TPC-H benchmark).
Possible options are: INFORMIX, DB2, TDAT (Teradata), SQLSERVER, SYBASE, ORACLE, VECTORWISE. Options stand for database syntax, by there is no MYSQL option.
dbgen creates '|' separated file (.tbl) with records for this tables.
I used ORACLE and it generated file with primary keys starting at 0.
You can comment if you know which option would be most similar to MySQL syntax and contain keys starting at 0.
Or is there any automatic software which will add 1 to primary keys in this file. Although NATION and REGION tables are not so big (20, 5), some other tables (which I removed from this question for clarity) will have over 100 000 records.
syntax is wrong, use this
ALTER TABLE NATION ADD CONSTRAINT NATION_FK FOREIGN KEY (N_REGIONKEY) REFERENCES REGION(R_REGIONKEY);
I have searched questions about this problem:
Similar question 01
Similar question 02
but I find they are not similar to my case.
Here is my tables:
Table 1 history:
create table if not exists history(
worker_num int(11),
cust_num int(11),
primary key (cust_num,worker_num)
)engine=innodb, default charset=utf8;
Table 2 customer:
drop table if exists customer;
create table if not exists customer(
cust_number int(11) not null,
foreign key (cust_number) references history(cust_num)
)engine=innodb, default charset utf8;
Table 3 worker:
drop table if exists worker;
create table if not exists worker(
worker_number int(11) not null,
foreign key (worker_number) references history(worker_num)
)engine=innodb, default charset=utf8;
I can create Table 1 and Table 2 successfully. However, when I try to create Table 3, It throws me an error like below:
Failed to add the foreign key constraint. Missing index for constraint 'fk_customer' in the referenced table 'history
Error code 1822.'
Question 01:
I know this is the problem of index. Because I found that if I put the Table3 creating code before Table2, I cannot create Table 2 successfully.
Thus, I know it must be caused by when the Table3 calls
foreign key (worker_number) references history(worker_num)
it will try to find the first primary key, primary key (cust_num,worker_num), in Table1 as its corresponding primary.
However, the first primary key in table 1 is cust_num and this cust_num is not the correct corresponding primary key to foreign key worker_num. Thus, it throws an error.
However, I search official Mysql document and find the description of index. It says:
MySQL requires indexes on foreign keys and referenced keys so that foreign key checks can be fast and not require a table scan. In the referencing table, there must be an index where the foreign key columns are listed as the first columns in the same order. Such an index is created on the referencing table automatically if it does not exist. This index might be silently dropped later if you create another index that can be used to enforce the foreign key constraint. index_name, if given, is used as described previously.
Here, you can see that Such an index is created on the referencing table automatically.
So, I'm very curious about if the referencing table is created automatically, why we cannot create child tables in any orders?(in my case, why should I create table 2 first or I will fail creating tables?)
Question 2:
In my case, I want define a foreign key in each child tables(table 2 and table 3) references to the primary keys in parent table(table 1). How to solve this index problem?
Appreciate any helps!!!
Thanks!
You have to read the documentation carefully:
(...) Such an index is created on the referencing table automatically if it does not exist. (...)
Emphasis: me
That is, you get the error because a suitable index on the referenced table is missing, not on the referencing table. The latter maybe crated automatically but not the former.
It also looks like you reversed the foreign key logic. Assuming that customer should list all the customers, worker all the workers and history some relationship between customers and workers, probably who has worked for who, then cust_number and worker_number should be primary key in the respective tables and there should be no foreign key in customer nor worker. In history there should be two (separate) foreign keys, cust_num pointing to customer and worker_num pointing to worker. The primary key definition of history is OK.
Got an odd problem I cant solve after browsing dozens of forum posts, and my local SQL Books.
I've got two tables, and want to add a foreign key to one of them. The foreign key and primary key share the same datatype and charset and yet I cannot add the Foreign Key at all.
addon_account
name
type
comments
id
int(11)
Primary Key
name
varchar(60)
Primary Key
label
varchar(255)
shared
int(11)
addon_account_data
name
type
comments
id
int(11)
Primary Key
account_name
varchar(60)
Primary Key
money
double
owner
varchar()
The query I ran:
ALTER TABLE `addon_account_data` ADD FOREIGN KEY (`account_name`) REFERENCES `addon_account`(`name`) ON DELETE RESTRICT ON UPDATE RESTRICT;
Can't get it to work. Tosses out the same issue the entire time.
You are creating a foreign key on addon_account_data(account_name) that references addon_account(name). You have a composite primary the referred table : addon_account(id, name).
This is not allowed in MySQL, as explained in the documentation:
MySQL requires indexes on foreign keys and referenced keys so that foreign key checks can be fast and not require a table scan. In the referencing table, there must be an index where the foreign key columns are listed as the first columns in the same order.
Possible solutions:
add an additional column in the referring table: addon_account_data(account_id, account_name) and create a composite primary key to the corresponding columns in addon_account
create an index on addon_account(name) (probably the simplest solution)
change the order of the columns in the primary key of the referred table, like: addon_account(name, id) (you might want to first consider the impacts this may have in terms of performance)
I am not exactly a MySQL guy, but:
I believe the problem is that you are referencing only part of the primary key:
Your table addon_account has a composite key PK(id, name).
So, to put your relationship to work, you will need to add 'account_id' as part of the foreign key as well:
ALTER TABLE addon_account_data ADD FOREIGN KEY (account_id, account_name) REFERENCES addon_account(id, name)
This thread deals with something similar.
I hope this helps.
EDITED
I have installed a MySQL server instance on my local machine... (MySQL 8).
I have run the script below, and it worked (giving warnings about integer display being a deprecated feature, so I would recommend ommitting it):
CREATE TABLE addon_account(
id INT(11) NOT NULL,
`name` VARCHAR(60) NOT NULL,
label VARCHAR(255),
shared INT(11),
CONSTRAINT pk_addon_account PRIMARY KEY(id, `name`));
CREATE TABLE addon_account_data (
id INT(11) NOT NULL,
account_name VARCHAR(60) NOT NULL,
account_id INT(11),
money DOUBLE,
`owner` VARCHAR(255),
CONSTRAINT pk_addon_account_data PRIMARY KEY(id, account_name),
CONSTRAINT fk_addon_account_account_data FOREIGN KEY(account_id, account_name)
REFERENCES addon_account(id, `name`));
Could you try it and see if this works for you?
I am not that familiar with MySQL.
make sure that the 2 tables have the same collation
like
COLLATE='utf8_general_ci'
As I continuously try to create a table with a couple of foreign key constraints I am running into a 'errno: 150' that gives no descriptive insight as to what is wrong with the table.
I have tried putting both foreign key constraints at the end of my code, spacing the words 'FOREIGN KEY' between the field reference but I was presented with the same error, with no detail as to what was wrong. Also, both of the tables being referenced exist.
CREATE TABLE line_Sales(
customer_id INT NOT NULL,
FOREIGN KEY(customer_id) REFERENCES d_customer(customer_id),
order_number INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
total_amt INT NOT NULL,
order_Date DATE,
product_key INT NOT NULL,
FOREIGN KEY(product_key) REFERENCES product_table(product_key),
purchase_channel VARCHAR(10)
);
the error is 1005 specifically errno:150
The generic nature of the MySQL error message is MySQL relaying an error returned from the InnoDB storage engine. The underlying problem is that InnoDB is refusing to create the foreign key constraint.
There's a number of possible reasons. The Usual reasons for InnoDB refusing to create foreign key constraints:
the datatypes of the referencing column(s) are not identical to the referenced columns
the referenced table name does not exist in the database
the referenced table is not InnoDB storage engine
the referenced column(s) do not exist in the referenced table
the referenced column(s) are not leading columns in an index
This list is not exhaustive. This is just a few of the most common reasons for the error.
As an aside... we should note that table names are case sensitive on some platforms with some file systems and some system variables settings.
Excerpt from MySQL Reference Manual:
it is best to adopt a consistent convention, such as always creating and referring to databases and tables using lowercase names. This convention is recommended for maximum portability and ease of use.
https://dev.mysql.com/doc/refman/8.0/en/identifier-case-sensitivity.html
Suggestions:
Check the definitions of the referenced tables i.e.
SHOW CREATE TABLE product_table ;
SHOW CREATE TABLE d_customer ;
compare the column names, datatypes, check that appropriate indexes exist.
Also we can create the table without foreign key constraints, and then attempt to add foreign key(s) in separate statement(s). This should help us narrow down the problem.
CREATE TABLE line_Sales (
customer_id INT NOT NULL,
order_number INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
total_amt INT NOT NULL,
order_Date DATE,
product_key INT NOT NULL,
purchase_channel VARCHAR(10)
);
Then as separate steps:
ALTER TABLE line_Sales
ADD CONSTRAINT FK_line_Sales_d_customer
FOREIGN KEY(customer_id) REFERENCES d_customer(customer_id)
ON UPDATE CASCADE ON DELETE RESTRICT ;
and
ALTER TABLE line_Sales
ADD CONSTRAINT FK_line_Sales_product
FOREIGN KEY(product_key) REFERENCES product_table(product_key)
ON UPDATE CASCADE ON DELETE RESTRICT ;
Note:
We expect that product_table exists and is InnoDB storage engine. We expect the column product_key exists in product_table. We expect that the datatype of product_key column matches exactly the datatype of the product_key column in line_sales. We expect there is an index defined on product_table that has product_key as the leading column. et al.
I have two tables, each with a provider column:
CREATE TABLE `title` (
`provider` varchar(40) CHARACTER SET latin1 NOT NULL,
CREATE TABLE `notification` (
`provider` varchar(40) CHARACTER SET latin1 NOT NULL,
However, when I try and add a foreign key
ALTER TABLE notification ADD FOREIGN KEY (provider) REFERENCES title (provider)
I get the following obscure error:
Can't create table 'metadata.#sql-c91_345b' (errno: 150)
Both of the tables are empty. Why is this occurring and what do I need to do to fix this?
http://dev.mysql.com/doc/refman/5.0/en/innodb-foreign-key-constraints.html says:
InnoDB requires indexes on foreign keys and referenced keys so that
foreign key checks can be fast and not require a table scan.
In the referencing table, there must be an index where the foreign key
columns are listed as the first columns in the same order.
Such an index is created on the referencing table automatically if it
does not exist.
(This is in contrast to some older versions, in which indexes had to
be created explicitly or the creation of foreign key constraints would
fail.) index_name, if given, is used as described previously.
I think you should create any (unique, primary, or plain) index for title.provider before creating a foreign key pointing to it.
Run SHOW ENGINE INNODB STATUS\G and look at the "LATEST FOREIGN KEY ERROR" to see more details on the error.