I am following along with a UDEMY course about SQL. The instructor is working in postgresql. I am working in MySQL workbench. Our corporate development is in MySQL 5.6 on the AWS platform. So I want to learn in MySQL.
There is a lecture about "creating tables" and using constraint and foreign key commands to link the primary keys in two different tables. This is something I want to do with my data, so the challenge is relevant. The instructor's code does not compile for me. I get "error code 1215. Cannot add foreign key constraint".
I have read here that the variables must have the exact same definition. So I changed the instructor's tables from "serial" to int. I am still getting the error. I have tried simplifying the code. I'm still not getting anywhere. Can anybody help me understand why it is not executing?
create table if not exists accounts(
user_id INT auto_increment not null,
username varchar(50) unique not null,
password varchar(50) not null,
email varchar(350) unique not null,
created_on timestamp not null,
last_login timestamp,
primary key (user_id)
);
create table if not exists role(
role_id INT auto_increment not null,
role_name varchar(250) unique not null,
PRIMARY KEY (role_id)
);
create table accounts_role(
user_id INT,
role_id INT,
grant_date timestamp,
primary key (user_id, role_id),
constraint accounts_role_role_id_fkey foreign key (role_id)
references role(role_id) match simple
on update no action
on delete no action,
constraint accounts_role_user_id_fkey foreign key (user_id)
references account (user_id) MATCH SIMPLE
on update no action
on delete no action
);
good grief.
Thanks Caius, i was implementing your suggestion and I found the answer to my problem.
i realized that my table is named "accounts" and i was creating a constraint on "account" ...
create table accounts_role(
user_id INT,
role_id INT,
grant_date timestamp,
primary key (user_id, role_id),
constraint accounts_role_role_id_fkey foreign key (role_id)
references role(role_id) match simple
on update no action
on delete no action,
constraint accounts_role_user_id_fkey foreign key (user_id)
references accounts(user_id) MATCH SIMPLE
on update no action
on delete no action
);
Related
I am using XAMPP server on Windows PC. Recently i was learning about and working with MySQL relational tables. I was creating a MySQL query to create a table with foreign key reference. My code is as follows:
CREATE TABLE loginattempts (
id int(16) NOT NULL,
loginattempts tinyint(9) NOT NULL,
attemptdate DATETIME NOT NULL
)
FOREIGN KEY (id) REFERENCES users(id)
ON DELETE CASCADE
ON UPDATE CASCADE
ENGINE = INNODB;
I have another table named users in my DB. When i execute the above query i get an error which is something like this:
Error [1064]: MySQL Syntax not correct Correspond to your MariaDB Documentation.
Is there anything wrong in my syntax if so please correct me!
Help will be highly appreciated. The above query is supposed to be written in PHP My Admin.
P.S.(If you find any mistakes feel free to edit)
The definition goes inside the create table statement:
CREATE TABLE loginattempts (
id int(16) NOT NULL,
loginattempts tinyint(9) NOT NULL,
attemptdate DATETIME NOT NULL,
FOREIGN KEY (id) REFERENCES users(id)
ON DELETE CASCADE
ON UPDATE CASCADE
) ENGINE = INNODB;
int(16) and tinyint(9) don't really make sense. An integer has up to 10 possible digits in its representation and a tinyint up to 3.
Often, foreign keys are given names. In addition, I recommend:
Each table have its own id, named after the table (i.e. userId rather than id).
Foreign keys have the same name as the primary key, where possible.
Constraints have names.
So, I would suggest:
CREATE TABLE loginattempts (
loginAttemptId int auto_increment primary key,
userId int NOT NULL,
loginattempts tinyint NOT NULL,
attemptdate DATETIME NOT NULL,
CONSTRAINT fk_loginattempts_userid FOREIGN KEY (userId) REFERENCES users(userId)
ON DELETE CASCADE
ON UPDATE CASCADE
) ENGINE = INNODB;
Of course, this requires changing the users table so the primary key is userId rather than id.
Here is a db<>fiddle.
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.
I have a database, I used these commands :
CREATE TABLE APPOINTMENT (app_id INT(5) NOT NULL, app_doctor INT(5) NOT NULL, app_date DATE, PRIMARY KEY (app_id));
CREATE TABLE APPPATIENTS (patient_ssn INT(10) NOT NULL, patient_name VARCHAR(20) NOT NULL, sex CHAR(1) NOT NULL, appointment_id INT(5), PRIMARY KEY (patient_ssn), UNIQUE (appointment_id));
ALTER TABLE APPPATIENTS ADD FOREIGN KEY (appointment_id) REFERENCES APPOINTMENT(app_id) ON DELETE CASCADE;
Now, I want to delete foreign key appointment_id in appPatients table :
ALTER TABLE apppatients DROP FOREIGN KEY appointment_id;
But I got an error :
Can't drop 'appointment_id'; check that column/key exists.
It is there! How can it give that error? What am I doing wrong?
I tried to create a database with your code and I notice the foreign key name appears different from appointment_id: reading with more attention the command definition, I notice that when you write
ADD FOREIGN KEY (appointment_id)
you are only saying the column on which the constraint will be created, not its name.
You can read the specifications here:
SQL FOREIGN KEY Constraint on ALTER TABLE
So, if you want to specify the name of the key, you have to write, for example:
alter table APPPATIENTS
ADD CONSTRAINT appointment_key
FOREIGN KEY (appointment_id)
REFERENCES appointment(app_id) ON DELETE CASCADE;
And so you know the name of the foreign key you created (appointment_key in this case).
If you want to know the foreign key name generated by mysql you can use the command
show create table APPPATIENTS;
that shows the complete table definition.
im new on mysql workbench, and i tried so many things to put my script working but i simply cant... Ive got these tables:
CREATE TABLE Utilizador (email varchar(40) not null, nome varchar(50)
not null, dataNascimento date, profissao varchar(50) not null,
reputacao double(3,2) unsigned not null, constraint pk_Utilizador
primary key(email))
This is the first table created!
CREATE TABLE POI (email varchar(40) not null, designacaoPOI
varchar(10) not null, coordenadaX int, coordenadaY int,
descricaoPOI varchar(200), constraint pk_POI primary key(email,
designacaoPOI), constraint fk_POI foreign key(email) references
Utilizador(email) on delete cascade)
This is the second table created!
CREATE TABLE Utilizador_POI (email varchar(40) not null, designacaoPOI
varchar(10) not null, constraint pk_Utilizador_POI primary key(email,
designacaoPOI), constraint fk1_Utilizador_POI foreign key(email)
references Utilizador(email) on delete cascade, constraint
fk2_Utilizador_POI foreign key(designacaoPOI) references
POI(designacaoPOI) on delete cascade)
This table gives me the error: Error Code: 1215. Cannot add foreign key constraint
I did some tests and im almost sure that the problem is in the foreign key "designacaoPOI". The other FK ("email") dont give me any error, so maybe the problem is in the Table POI?
Thanks in advanced!
The problem here is twofold:
1/ Use IDs for PRIMARY KEYs
You should be using IDs for primary keys rather than VARCHARs or anything that has any real-world "business meaning". If you want the email to be unique within the Utilizador table, the combination of email and designacaoPOI to be unique in the POI table, and the same combination (email and designacaoPOI) to be unique in Utilizador_POI, you should be using UNIQUE KEY constraints rather than PRIMARY KEY constraints.
2/ You cannot DELETE CASCADE on a FOREIGN KEY that doesn't reference the PRIMARY KEY
In your third table, Utilizador_POI, you have two FOREIGN KEYs references POI. Unfortunately, the PRIMARY KEY on POI is a composite key, so MySQL has no idea how to handle a DELETE CASCADE, as there is not a one-to-one relationship between the FOREIGN KEY in Utilizador_POI and the PRIMARY KEY of POI.
If you change your tables to all have a PRIMARY KEY of ID, as follows:
CREATE TABLE blah (
id INT(9) AUTO_INCREMENT NOT NULL
....
PRIMARY KEY (id)
);
Then you can reference each table by ID, and both your FOREIGN KEYs and DELETE CASCADEs will work.
I think the problem is that Utilizador_POI.email references POI.email, which itself references Utilizador.email. MySQL is probably upset at the double-linking.
Also, since there seems to be a many-to-many relationship between Utilizador and POI, I think the structure of Utilizador_POI isn't what you really want. Instead, Utilizador_POI should reference a primary key from Utilizador, and a matching primary key from POI.
The problem is in your second table. Your primary key is (email,designacaoPOI), when you try to reference that in your table it gives you error because of this:
InnoDB permits a foreign key to reference any index column or group of
columns. However, in the referenced table, there must be an index
where the referenced columns are listed as the first columns in the
same order.
For it to work, either change the order of your second tale PRIMARY KEY :
CREATE TABLE POI (
email VARCHAR(40) NOT NULL,
designacaoPOI VARCHAR(10) NOT NULL,
coordenadaX INT,
coordenadaY INT,
descricaoPOI VARCHAR(200),
CONSTRAINT pk_POI PRIMARY KEY (designacaoPOI,email), -- changed the order
CONSTRAINT fk_POI FOREIGN KEY (email)
REFERENCES Utilizador(email) ON DELETE CASCADE
);
sqlfiddle demo
or add an index for designacaoPOI:
CREATE TABLE POI (
email VARCHAR(40) NOT NULL,
designacaoPOI VARCHAR(10) NOT NULL,
coordenadaX INT,
coordenadaY INT,
descricaoPOI VARCHAR(200),
CONSTRAINT pk_POI PRIMARY KEY (designacaoPOI,email),
KEY key_designacaoPOI(designacaoPOI), -- added index for that column
CONSTRAINT fk_POI FOREIGN KEY (email)
REFERENCES Utilizador(email) ON DELETE CASCADE
);
sqlfiddle demo
Either of these solutions will let you create your third table without errors.
my java cannot execute this code, and gives me error like "cannot add key constraint"
Please Help me
st.executeUpdate("CREATE TABLE `e166713`.`shopping` ( "
`idShopping` INT NOT NULL,
`idUser` VARCHAR(45) NULL,
PRIMARY KEY (`idShopping`),
INDEX `user_idx` (`idUser` ASC),
CONSTRAINT `user`
FOREIGN KEY (`idUser`)
REFERENCES `e166713`.`user` (`uID`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)");
This could mean two things:
Either user table is not created yet
or
uID in user table is not of the same data type as idUser :
varchar(45).
The columns need to be the exact same data type in both tables.
sqlfiddle demo