How to add foreign key to table in mysql - mysql

What I am doing incorrect? Trying to create these tables in sqlfiddle
does not work gives
Cannot add foreign key constraint
create table product (
pid int NOT NULL,
name varchar(10),
PRIMARY KEY (pid)
);
create table trans (
tid int NOT NULL ,
productId int NOT NULL,
userId int NOT NULL,
PRIMARY KEY (tid),
FOREIGN KEY (productId) REFERENCES product(pid),
FOREIGN KEY (userId) REFERENCES user1(uid)
);
create table user1 (
uid int NOT NULL ,
location varchar(22),
PRIMARY KEY (uid)
);

As #BillKarwin mentioned, the definitions for tables containing primary keys referenced by the trans table should appear before the definition for the trans table. So you should move the definition for the trans table to last.
However, even doing this still results in an error in SQLFiddle:
SQLFiddle (uncomment the foreign key reference in trans)
SQLFiddle seems to have some sort of problem with accepting this table schema. This is not surprising, as the site seems to have such problems frequently.

What is order you create tables. You need first to create product and user1 and at the end - trans.

Related

MySQL composite primary key and foreign keys at the same time

I'm trying to create a web application about cooking, and I get weird behaviours when creating my MySQL database. I have the following tables: friends and user, described as below
CREATE TABLE IF NOT EXISTS user (
user_id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
username VARCHAR (100) UNIQUE NOT NULL,
password VARCHAR(255) NOT NULL
);
CREATE TABLE IF NOT EXISTS friends (
user_id int NOT NULL,
friend_id int NOT NULL,
PRIMARY KEY (user_id, friend_id),
FOREIGN KEY (user_id) REFERENCES user(user_id),
FOREIGN KEY (friend_id) REFERENCES user(user_id)
);
For some reason, in my friends table, the composite primary key gets created, but only the second field friend_id is a foreign key. I have the exact same problem when I create a table named recipe_composition, when I create a composite key recipe_id, ingredient_id. The composite primary keys gets created but only the second field ingredient_id gets the foreign key reference.
Any help would be appreciated, thank you.

Make mySQL column unique for each foreign key

Let's say I have the following column in my database:
Item:
id int PRIMARY KEY,
name string,
foreign_id FOREIGN KEY
Is there a way without querying the database before insertion each time, that one foreign key cannot contain two rows with the same name?
Sure, you want to add an (unique) index for your foreign key column.
The SQL command to add that is
ALTER TABLE `mytable`
ADD UNIQUE INDEX `mytable_idx__1` (`foreign_id`);
If I understand correctly, you might want to use the UNIQUE constraint:
CREATE TABLE (
id INT PRIMARY KEY
, name VARCHAR(50) --or whatever you need
, foreign_id INT UNIQUE
FOREIGN KEY (foreign_id) REFERENCES...
);
As i Understand using FOREIGN KEY (foreign_id) REFERENCES --- will solve it. And make sure that the always make a unique key of table as foreign key for other table.
CREATE TABLE profile
(
id int NOT NULL PRIMARY KEY,
name varchar(50),
FOREIGN KEY (name)
REFERENCES member (name)
ON DELETE CASCADE
ON UPDATE CASCADE
) ENGINE=InnoDB ;

How do I make a column not null and be a foreign key in MySQL

I am trying to create a table that is a foreign key of another table and make it not null, but I am running into trouble making both happen. I was able to successfully get foreign keys working that did not require NOT NULL but I can't get both working.
Here is the line giving me trouble
CONSTRAINT instructor FOREIGN KEY (id) REFERENCES Instructor(id) NOT NULL
then I get the error:
CONSTRAINT instructor FOREIGN KEY (id) REFERENCES Instructor(id) NOT NULL,
*
ERROR at line 5:
ORA-00907: missing right parenthesis
Also, I am getting a weird error when trying to create a table (note, this table is created after creating the table that contains the above error) where it fails at a very trivial part:
CREATE TABLE Enrollment (
CONSTRAINT class_id FOREIGN KEY (id) REFERENCES Class(id) NOT NULL,
CONSTRAINT member_id FOREIGN KEY (id) REFERENCES RecCenterMember(id) NOT NULL,
cost int NOT NULL
);
Then for that command I get this error:
CREATE TABLE Enrollment (
*
ERROR at line 1:
ORA-00904: : invalid identifier
How can I fix these two errors?
You need to create the column before you try creating constraints on the column.
You have:
CREATE TABLE Enrollment (
CONSTRAINT class_id FOREIGN KEY (id) REFERENCES Class(id) NOT NULL,
CONSTRAINT member_id FOREIGN KEY (id) REFERENCES RecCenterMember(id) NOT NULL,
cost int NOT NULL
);
You need:
CREATE TABLE Enrollment (
id INT NOT NULL CONSTRAINT class_id REFERENCES Class(id),
CONSTRAINT member_id FOREIGN KEY (id) REFERENCES RecCenterMember(id),
cost INT NOT NULL
);
Note that in the first line, the FOREIGN KEY isn't necessary because the column is implied. In the second line, the id is identified. You could also write:
CREATE TABLE Enrollment
(
id INT NOT NULL,
CONSTRAINT class_id FOREIGN KEY (id) REFERENCES Class(id),
CONSTRAINT member_id FOREIGN KEY (id) REFERENCES RecCenterMember(id),
cost INT NOT NULL
);
It is unusual, though not automatically wrong, to make a single column (id) be a foreign key of two tables simultaneously. It isn't clear if you actually want three columns in your table — and if you do, which column names are in your table.
You could also use the appropriate notation for an automatically allocated type in MySQL syntax (SERIAL instead of INT NOT NULL, or add AUTO_INCREMENT, etc).
Maybe you're really after:
CREATE TABLE Enrollment
(
id SERIAL,
class_id INT NOT NULL CONSTRAINT class_id REFERENCES Class(id),
member_id INT NOT NULL CONSTRAINT member_id REFERENCES RecCenterMember(id),
cost INT NOT NULL
);
This makes more sense in general. You're creating a new enrollment record for a pre-existing class, and for a pre-existing recreation centre member, and recording its cost.
Syntax diagrams vs actual behaviour
If, as Michael - sqlbot suggests — and I've no reason whatsoever to disbelieve him — MySQL recognizes but does not respond to the REFERENCES clause in a column definition in a CREATE TABLE statement but only acts on full FOREIGN KEY clauses, then you have to adjust my suggested answers from their syntactically correct but semantically ignored form to something like:
Option 1 (minimally changing the SQL from the question):
CREATE TABLE Enrollment (
id INT NOT NULL,
CONSTRAINT class_id FOREIGN KEY (id) REFERENCES Class(id),
CONSTRAINT member_id FOREIGN KEY (id) REFERENCES RecCenterMember(id),
cost int NOT NULL
);
Option 2 (what I consider the most plausible version):
CREATE TABLE Enrollment
(
id SERIAL,
class_id INT NOT NULL,
CONSTRAINT fk_class_id FOREIGN KEY (class_id) REFERENCES Class(id),
member_id INT NOT NULL,
CONSTRAINT fk_member_id FOREIGN KEY (member_id) REFERENCES RecCenterMember(id),
cost INT NOT NULL
);
Or some other variant of this syntax based on the desired table schema ignoring the FK constraints, then adding the constraints along the lines shown.
Key Point
You must define the columns before you define the foreign keys based on those columns.

Altering MySQL table to add foreign key constraint leads to errors

Question:
Why am I getting errors when trying to alter a table with a foreign key constraint?
Details:
I have 1 table, HSTORY which I use as a base table for all other specific history tables (ie. USER_HISTORY, BROWSER_HISTORY, PICTURE_HISTORY...). I have also included the PICTURE and USER tables as they get called as well.
HISTORY table:
CREATE TABLE IF NOT EXISTS HISTORY
(
ID INT NOT NULL AUTO_INCREMENT,
VIEWERID INT NOT NULL ,
VIEWDATE TIMESTAMP NOT NULL DEFAULT NOW(),
PRIMARY KEY (ID),
FOREIGN KEY (VIEWERID) REFERENCES USER(ID)
)
engine=innodb;
USER table: (in case anyone is curious)
CREATE TABLE IF NOT EXISTS USER
(
ID INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY (ID)
)
engine=innodb;
PICTURE table: (in case anyone is curious)
CREATE TABLE IF NOT EXISTS PICTURE
(
ID INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY (ID)
)
engine=innodb;
PICTURE_HISTORY table:
CREATE TABLE IF NOT EXISTS PICTURE_HISTORY LIKE HISTORY;
ALTER TABLE PICTURE_HISTORY
ADD FOREIGN KEY (FOREIGNID) REFERENCES PICTURE(ID);
However, when I do this, I get:
Key column 'FOREIGNID' doesn't exist in table
I take this to mean that I have to first create FOREIGNID, but in many of the examples on SO, the above should work. Anyone know why this is occurring?
Thanks to Michael for pointing out my mistake. I can't actually make a foreign key unless the column already exists. If instead I issue these two commands, the foreign key constraint is created:
ALTER TABLE PICTURE_HISTORY
ADD COLUMN FOREIGNID INT NOT NULL;
ALTER TABLE PICTURE_HISTORY
ADD FOREIGN KEY (FOREIGNID) REFERENCES PICTURE(ID);
You can combine commands for mysql using a comma, like so:
ALTER TABLE PICTURE_HISTORY
ADD COLUMN FOREIGNID INT NOT NULL,
ADD FOREIGN KEY (FOREIGNID) REFERENCES PICTURE(ID);

Nesting of groups or elements

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 ;