I am trying to add a self relation in an existing Innodb table here is table structure
Table person
person_id int (10) primary key not null auto increment,
parent_id int (10) NULL default null,
name varchar(30)
When I use this command
ALTER TABLE `person` ADD FOREIGN KEY ( `parent_id` ) REFERENCES `person` (`person_id`) ON DELETE RESTRICT ON UPDATE RESTRICT ;
I get the error data type mismatch. I think this could be due to null values in parent_id. Is there any way to skip this check?
Thanks
person_id and parent_id need to be the exact same data type. For example, if person_id is INT UNSIGNED and parent_id is INT, then you can't create the foreign key.
Run this command and compare the data types of the two columns:
SHOW CREATE TABLE `person`\G
Related
Table 1
create table personal(
id int not null auto_increment unique,
name char(20) not null,
age int not null,
city varchar(20) not null default 'Delhi'
);
insert into personal(name,age,city) values
('anubhav',22,'delhi'),
('rohit',24,'agra');
Table 2
create table applications(
app_id int(5) not null auto_increment unique,
city varchar(10) not null default 'Delhi'
);
insert into applications(city) values
('kolkata'),
('mumbai'),
('mumbai'),
('delhi'),
('agra'),
('agra');
Then i apply foreign key here with the help of Alter command-
alter table personal add foreign key(city) references applications(app_id)
but i am getting an error: ERROR 1005 (HY000): Can't create table 'student.#sql-f40_3' (errno: 150)
MySQL specifies:
Conditions and Restrictions
1.Corresponding columns in the foreign key
and the referenced key must have similar data types. The size and sign
of fixed precision types such as INTEGER and DECIMAL must be the same.
The length of string types need not be the same. For nonbinary
(character) string columns, the character set and collation must be
the same.
2.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.
The data type must be the same.
You could do:
alter table personal add foreign key(city) references applications(city)
But, the columns on both tables should be indexed.
See here
you desing in not normalized
your personal table should only reference the id.
City name in the applications should be unique, so i added it in the create table, there is no need for two or more delhis in a table(see normalisation)
If you really want to use in personal the city name, you must like i already made refernece the coty name of appcations or define a KEY for that column.
Further the datatyoes of the columns must always be the saem in both table for the foreign key
create table personal(
id int not null auto_increment unique,
name char(20) not null,
age int not null,
city int not null default 0
);
create table applications(
app_id int not null auto_increment primary key,
city varchar(10) not null unique default 'Delhi'
);
alter table personal add foreign key(city) references applications(app_id)
You have small bugs such as not putting null in the insert for the autoincrement and if it is primary key you should not put not null.
Table personal
create table personal(
id int auto_increment primary key,
name char(20) not null,
age int not null,
city varchar(20) not null default 'Delhi'
);
insert into personal values (null,'anubhav',22,'delhi'),
(null,'rohit',24,'agra');
Table applications
create table applications(
app_id int(5) auto_increment primary key,
city varchar(10) not null default 'Delhi'
);
insert into applications values(null,'kolkata'),
(null,'mumbai'),
(null,'mumbai'),
(null,'delhi'),
(null,'agra'),
(null,'agra');
Alter table
alter table personal add foreign key(city) references applications(app_id)
Lets say I have the following table:
CREATE TABLE IF NOT EXISTS tbl_mg_accounts (
account_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,L,
holder_id INT NOT NULL,
FOREIGN KEY (holder_id) REFERENCES tbl_mg_holders(holder_id) ON UPDATE CASCADE ON DELETE CASCADE
);
I want to add another column that auto-fills but it's based on a column within the foreign table reference.
E.g.
CREATE TABLE IF NOT EXISTS tbl_mg_accounts (
account_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,L,
holder_id INT NOT NULL,
username VARCHAR(50) NOT NULL,
test_col VARCHAR(100) GENERATED ALWAYS AS CONCAT(tbl_mg_holders.holder_name, username) VIRTUAL,
FOREIGN KEY (holder_id) REFERENCES tbl_mg_holders(holder_id) ON UPDATE CASCADE ON DELETE CASCADE
);
This is giving me an error...
Perhaps the addition of below is a syntax issue or is this actually a limitation with MySQL/MariaDB?
test_col VARCHAR(100) GENERATED ALWAYS AS CONCAT(tbl_mg_holders.holder_name, username) VIRTUAL
Ok Yes this seems like a limitation.
I've instead created a VIEW for my requirements and let the backend process this way.
I don't dabble much in SQL design at all, so this might be a trivial question.
I have a players table:
CREATE TABLE players(
p_id INT NOT NULL PRIMARY KEY,
p_name VARCHAR(150) NOT NULL
)
I have a results table:
CREATE TABLE results(
f_id INT NOT NULL PRIMARY KEY,
f_datetime DATETIME NOT NULL,
p1_id INT NULL,
p2_id INT NULL,
FOREIGN KEY (p1_id) REFERENCES players(p_id) ON DELETE SET NULL ON UPDATE SET NULL,
FOREIGN KEY (p2_id) REFERENCES players(p_id) ON DELETE SET NULL ON UPDATE SET NULL
)
When I add an INSERT into the results table, I am adding the p1_id and p2_id. For this to work, I need to already have these id's defined in the players table, with the accompanying string name for this id. Programmatically, what should I do with my data before adding to the results table?
Check if p_id exists (from my p1_id and p2_id values), if not, INSERT them with the accompanying string.
Add my data into the results table as a normal insert
Or is there a more conventional way to do these things? Maybe some SQL quirk i'm not aware of?
Is order of execution important when creating Primary/Foreign Key links in a MySQL statement?
For example, the following code will produce the error: "Cannot add foreign key constraint"
CREATE TABLE IF NOT EXISTS Movies
(
MovieID INT NOT NULL AUTO_INCREMENT,
GenreID INT NOT NULL,
PRIMARY KEY(MovieID),
FOREIGN KEY(GenreID) References Genres(GenreID)
);
CREATE TABLE IF NOT EXISTS Genres
(
GenreID INT NOT NULL AUTO_INCREMENT,
GenreName VARCHAR(30),
Primary key (GenreID)
);
Cannot add foreign key constraint
But when the Genre table is created FIRST, the error no longer persists:
CREATE TABLE IF NOT EXISTS Genres
(
GenreID INT NOT NULL AUTO_INCREMENT,
GenreName VARCHAR(30),
Primary key (GenreID)
);
CREATE TABLE Movies
(
MovieID INT NOT NULL AUTO_INCREMENT,
GenreID INT NOT NULL,
PRIMARY KEY(MovieID),
FOREIGN KEY(GenreID) References Genres(GenreID)
);
Schema Ready
Is the error caused because the table hasn't been created yet, so it doesn't know where / what the Genre tables PK type is?
When I was searching for a solution to foreign key constraints all I found was information on the data type matching, but not the order of execution. Thanks.
Is the error caused because the table hasn't been created yet, so it doesn't know where / what the Genre tables PK type is?
Yes.
If you define the Movies table first, MySQL is going to try to find the referenced Genres table, which does not yet exist. So you should create them in the opposite order:
CREATE TABLE IF NOT EXISTS Genres
CREATE TABLE IF NOT EXISTS Movies
Foreign key is a reference to another key: primary key. If primary key doesn't exist now, you can not reference to an unknown thing, so you get exception.
I'm fairly new in Mysql, but I have problem that I cannot solve. I will give you an example to demonstrate it. Please note that I know that (for current example) there are other simpler and more efficient ways to solve it... but just take it as an example of the required procedure.
First the data: The data would be the name of a Person.
CREATE TABLE person(
id INT,
name VARCHAR(100)
) TYPE=innodb;
Second: Group Creation... So this is fairly simple... and could easily done using a table 'group' with a foreignkey to person. These groups could be arbitrary, containing any number of persons, duplicated... or not... (that is simple!!)
Third: MY REAL PROBLEM--- I also would like to have Groups that have other Groups as elements (instead of persons). This is where a really get stuck, because I know how to create a groups of persons, a group of groups (having a self-referencing foreign key)... but I don't know how to create a group that MAY HAVE persons AND Groups.
I appreciate any suggestion to solve this issue.
Thank you very much for your comments.
Regards
ACombo
I'd go with firstly setting up the myGroup and person tables.
Secondly, I'd set up a myGroupGroup table with columns myGroupId, parentMyGroupId. This will allow you to relate group rows to child group rows i.e. "this group has these groups within it". If a group has no rows in this table then it has no child groups within it.
Thirdly, I'd set up a personGroup table with columns personId, myGroupId. This will allow you to relate person rows to a given group. If a group has no rows in this table then it has no persons within it.
CREATE TABLE person(
id INT UNSIGNED PRIMARY KEY,
name VARCHAR(100)
) ENGINE=innodb;
CREATE TABLE myGroup(
id INT UNSIGNED PRIMARY KEY,
groupName VARCHAR(100)
) ENGINE=innodb;
-- Holds groups within groups
CREATE TABLE myGroupGroup(
id INT UNSIGNED PRIMARY KEY,
myGroupId INT UNSIGNED,
parentMyGroupId INT UNSIGNED DEFAULT NULL,
CONSTRAINT `fk_myGroupGroup_group1` FOREIGN KEY (`parentMyGroupId`) REFERENCES `myGroup` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `fk_myGroupGroup_group2` FOREIGN KEY (`myGroupId`) REFERENCES `myGroup` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=innodb;
-- Holds persons within a group
CREATE TABLE personGroup(
id INT,
personId int UNSIGNED NOT NULL,
myGroupId int UNSIGNED NOT NULL,
CONSTRAINT `fk_personGroup_group1` FOREIGN KEY (`myGroupId`) REFERENCES `myGroup` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `fk_personGroup_person1` FOREIGN KEY (`personId`) REFERENCES `person` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=innodb;
I've tweaked your SQL a bit:
1) Replaced TYPE with ENGINE
2) Replaced table name group with myGroup (GROUP is a reserved word)
Good luck!
Alternative:
CREATE TABLE Entity
( EntityId INT --- this id could be AUTO_INCREMENT
, PRIMARY KEY (EntityId)
) ENGINE = InnoDB ;
CREATE TABLE Person
( PersonId INT --- but not this id
, PersonName VARCHAR(100)
, PRIMARY KEY (PersonId)
, FOREIGN KEY (PersonId)
REFERENCES Entity(EntityId)
) ENGINE = InnoDB ;
CREATE TABLE Grouping
( GroupingId INT --- and neither this id
, GroupingName VARCHAR(100)
, PRIMARY KEY (GroupingId)
, FOREIGN KEY (GroupingId)
REFERENCES Entity(EntityId)
) ENGINE = InnoDB ;
CREATE TABLE Belongs
( EntityId INT
, GroupingID INT
, PRIMARY KEY (EntityId, GroupingId)
, FOREIGN KEY (EntityId)
REFERENCES Entity(EntityId)
, FOREIGN KEY (GroupingID)
REFERENCES Grouping(GroupingId)
) ENGINE = InnoDB ;