error with cross referenced foreign key constraints - sql

I had a weird problem when I am trying to create tables in MySQL.
I want to have a cross reference two many-to-many tables and here is the code I create table
create table teacher(
t_id char(10) not null unique,
name varchar(20) not null,
sur_name varchar(20) not null,
CONSTRAINT pk_teacher PRIMARY KEY(t_id))
create table student(
s_id char(10) not null unique,
name varchar(20) not null,
sur_name varchar(20) not null,
CONSTRAINT pk_student PRIMARY KEY(s_id))
create table teacher_student(
t_id char(10) not null,
s_id char(10) not null,
CONSTRAINT pk_teacher_student PRIMARY KEY(t_id, s_id))
in order to add foreign constraints I used the following code
ALTER TABLE teacher_student
ADD CONSTRAINT fk_teacher_student FOREIGN KEY(s_id) REFERENCES student(s_id)
ALTER TABLE teacher_student
ADD CONSTRAINT fk_student_teacher FOREIGN KEY(t_id) REFERENCES teacher(t_id)
ALTER TABLE student
ADD CONSTRAINT fk_student_teacher_student
FOREIGN KEY(s_id) REFERENCES teacher_student(s_id)
ALTER TABLE teacher
ADD CONSTRAINT fk_teacher_teacher_student
FOREIGN KEY(t_id) REFERENCES teacher_student(t_id)
that works fine but if I try to execute code in a different order like this
ALTER TABLE student
ADD CONSTRAINT fk_student_teacher_student
FOREIGN KEY(s_id) REFERENCES teacher_student(s_id)
ALTER TABLE teacher
ADD CONSTRAINT fk_teacher_teacher_student
FOREIGN KEY(t_id) REFERENCES teacher_student(t_id)
ALTER TABLE teacher_student
ADD CONSTRAINT fk_teacher_student FOREIGN KEY(s_id) REFERENCES student(s_id)
ALTER TABLE teacher_student
ADD CONSTRAINT fk_student_teacher FOREIGN KEY(t_id) REFERENCES teacher(t_id)
ALTER TABLE student
I am getting exception
Can't create table 'test.#sql-44c_37' (errno: 150)
My question is, why the order is important? what is the difference between these two ways of creating constraints? thanks

"I try to execute code in a different order like this" You have no different order you have extremely different constraints. You can't create such constraints.
Examine this article for more information
FOREIGN KEY Constraints

Some of your foreign keys don't seem to make any sense.
Those referencing student and teacher (the fk_teacher_student and fk_student_teacher ones) are fine. That's actually a typical case of a many-to-many table referencing each of the two entity tables whose many-to-many relationship is being implemented.
Now, what are you proposing with referencing back from those tables to the many-to-many one? I admit that I can't really explain why the foreign keys were successfully added using the first script and failed with the other. Sorry about that. Even though I've got some vague idea, that's not really the point of my answer. The point is, your present design is going to make it difficult for you to add new data. With it, you can't really add, say, a student without adding also a relationship between the new student and an existing teacher. This is because a row in student is supposed to reference an existing student in teacher_student, but since it is a new student, there's no corresponding row in teacher_student yet. Same goes for a new teacher.
So, consider just abandoning the idea of fk_student_teacher_student and fk_teacher_teacher_student. They are not needed to your design. They have already caused you to solve an unnecessary problem and they are likely to cause more trouble in the future.

Related

Create table with foreign key to an other table created below in sql file

My problem is that i have two tables with each table having a foreign key to the other table.
Each time , i execute the SQL file containing the creation of the two tables, it gives me an error that he doesn't find the other table. I'm working with sqlplus to execute the sql file.
Here's an example of SQL file i tried with :
create table A(
Age number(3),
name number(3) constraint A_FK references B(name))
/
create table B(
Age number(3) constraint B_FK references A(Age),
name number(3))
And even if i reverse the order, it gives the same error.
Thanks for help.
This is a problem of cycles in foreign keys. One method is to add all foreign keys after table creation (as I think the other answers propose).
You can also just do that for the first table:
create table A (
Age number(3) primary key,
name number(3)
);
create table B (
name number(3) primary key,
Age number(3),
constraint B_FK foreign key (age) references A(Age)
);
alter table B add constraint A_FK foreign key (name) references B(name);
Here is a db<>fiddle.
Notes:
Foreign keys should reference primary keys, so I added that declaration as well.
I recommend making the primary key the first column in the table.
You can also define the constraint inline for one of the tables (i.e. age number(3) constraint b_fk references a(age)).
The table column(s) that is referred by a foreign key must exist at the time when the constraint is created. Since you have some kind of cyclic reference between the tables, you need to do this in three steps:
first create one table without the foreign key
create the second table (with its foreign key)
finally add the foreign key to the first table with an alter table statement
You also need the referred column to have a unique or primary key constraint set up, otherwise you would get error ORA-02270: no matching unique or primary key for this column-list.
create table A(
age number(3) primary key,
name number(3)
);
create table B(
age number(3) constraint B_FK references A(Age),
name number(3) primary key
);
alter table A add constraint A_FK foreign key (name) references B(name);
Demo on DB Fiddle
Side note: I am quite suspicious about your sample structure, but this could be because your oversimplified it in the question.
It fails because the reference table doesn't exist yet.
Create the tables without the key first. Then drop one and recreated it with the reference. Then drop the 2nd and recreate it with the reference.
Create table first and then ADD the CONSTRAINT
ALTER TABLE A
ADD FOREIGN KEY (name) REFERENCES B(name);
ALTER TABLE B
ADD FOREIGN KEY (age) REFERENCES A(age);

Difference between using or not using CONSTRAINT keyword on SQL Server

What is the difference between using or not using the CONSTRAINT keyword when working with Foreign Keys on SQL Server?
I noticed that apparently both worked the same in this specific case, without CONSTRAINT:
CREATE TABLE ClientsPhones
(
ClientPhone varchar(10) NOT NULL,
ClientID smallint NOT NULL,
PRIMARY KEY (ClientPhone),
FOREIGN KEY (ClientID) REFERENCES Clients(ClientID)
);
And with CONSTRAINT:
CREATE TABLE ClientsPhones
(
ClientPhone varchar(10) NOT NULL,
ClientID smallint NOT NULL,
PRIMARY KEY (ClientPhone),
CONSTRAINT fk_ClientID
FOREIGN KEY (ClientID) REFERENCES Clients(ClientID)
);
Both didn't let me add records to the table unless the ClientID already existed on the Clients table, and the same ClientID and ClientPhone weren't already on the ClientsPhones table.
Is there any real difference between the two besides the fact that I'm able to name the constraint?
If you don't create constraint.it will automatically create own constraint name
the foreign key index name is generated using the name of the referencing foreign key column Automatically.
So there is no way to see difference of using and not using Constraint keyword. by default constraint name will be defined.
I did some research and don't believe Hell Boy's answer was as clear as it could be and had some misinformation.
Every constraint you add to a database has a name set by default. This includes PRIMARY KEY, FOREIGN KEY, DEFAULT, NOT NULL. It isn't necessarily the name of the column(s) used.
You can imagine that when you don't use the CONSTRAINT keyword SQL Server puts it there as well as generates a name for you.
If you want to remove or change a constrain you would either have to delete the entire table and recreate it with the correct constraints or you can reference the constraint by name and then alter it somewhat like a column using the ALTER keyword. This can be useful for when you need to delete a table with a foreign key. If you name the foreign key constraint you can delete it and then the table instead of having to delete the table the foreign key points to.

How to add a foreign key referring to itself in SQL Server 2008?

I have not seen any clear, concise examples of this anywhere online.
With an existing table, how do I add a foreign key which references this table? For example:
CREATE TABLE dbo.Projects(
ProjectsID INT IDENTITY(1,1) PRIMARY KEY,
Name varchar(50)
);
How would I write a command to add a foreign key which references the same table? Can I do this in a single SQL command?
I'll show you several equivalent ways of declaring such a foreign key constraint. (This answer is intentionally repetitive to help you recognise the simple patterns for declaring constraints.)
Example: This is what we would like to end up with:
Case 1: The column holding the foreign keys already exists, but the foreign key relationship has not been declared / is not enforced yet:
In that case, run this statement:
ALTER TABLE Employee
ADD FOREIGN KEY (ManagerId) REFERENCES Employee (Id);
Case 2: The table exists, but it does not yet have the foreign key column:
ALTER TABLE Employee
ADD ManagerId INT, -- add the column; everything else is the same as with case 1
FOREIGN KEY (ManagerId) REFERENCES Employee (Id);
or more succinctly:
ALTER TABLE Employee
ADD ManagerId INT REFERENCES Employee (Id);
Case 3: The table does not exist yet.
CREATE TABLE Employee -- create the table; everything else is the same as with case 1
(
Id INT NOT NULL PRIMARY KEY,
ManagerId INT
);
ALTER TABLE Employee
ADD FOREIGN KEY (ManagerId) REFERENCES Employee (Id);
or, declare the constraint inline, as part of the table creation:
CREATE TABLE Employee
(
Id INT NOT NULL PRIMARY KEY,
ManagerId INT,
FOREIGN KEY (ManagerId) REFERENCES Employee (Id)
);
or even more succinctly:
CREATE TABLE Employee
(
Id INT NOT NULL PRIMARY KEY,
ManagerId INT REFERENCES Employee (Id)
);
P.S. regarding constraint naming: Up until the previous revision of this answer, the more verbose SQL examples contained CONSTRAINT <ConstraintName> clauses for giving unique names to the foreign key constraints. After a comment by #ypercube I've decided to drop these clauses from the examples, for two reasons: Naming a constraint is an orthogonal issue to (i.e. independent from) putting the constraint in place. And having the naming out of the way allows us to focus on the the actual adding of the constraints.
In short, in order to name a constraint, precede any mention of e.g. PRIMARY KEY, REFERENCES, or FOREIGN KEY with CONSTRAINT <ConstraintName>. The way I name foreign key constraints is <TableName>_FK_<ColumnName>. I name primary key constraints in the same way, only with PK instead of FK. (Natural and other alternate keys would get the name prefix AK.)
You can add the column and constraint in one operation
ALTER TABLE dbo.Projects ADD
parentId INT NULL,
CONSTRAINT FK FOREIGN KEY(parentid) REFERENCES dbo.Projects
Optionally you could specify the PK column in brackets after the referenced table name but it is not needed here.
If the table already exists: Assuming you don't already have a column to store this data. If you do then skip this step.
ALTER TABLE [dbo].[project]
ADD [fkProjectsId] INT;
GO
ALTER TABLE [dbo].[projects]
ADD CONSTRAINT [FK_Projects_ProjectsId] FOREIGN KEY ([fkProjectsId]) REFERENCES [dbo].[Projects] ([ProjectsID])
GO

Is it possible to reference a primary key in one table as a foreign key constraint across more than 2 tables?

I am currently making a database back end system on an airport, using sql through the phpmyadmin server. The criteria is not meant to be perfect but one of the ideas behind the queries is to imagine that either a customer or flight dispatch officer might be looking at the tables. I was wondering if it was possible to reference a primary key as a foreign key across 2 or more tables. In the example below, I want to reference the model number as a foreign key in the bottom 2 tables. I have ensured that the type and character count are the same.
CREATE TABLE Aircraft_Model
(Model_Number varchar (12) NOT NULL,
seat_capacity int (3),
CONSTRAINT pk7 primary key (Model_Number));
CREATE TABLE Licence_type
(Rank varchar (25) NOT NULL,
Model_Number varchar (12),
CONSTRAINT pk9 primary key (Rank));
CREATE TABLE Aircraft
(Aircraft_ID varchar (4) NOT NULL,
Model_Number varchar(12),
airport_base text(13),
CONSTRAINT pk1 PRIMARY KEY (Aircraft_ID));
Is this possible? I only want the database to be able to perform about 12-15 simple queries.
Would the syntax of adding a foreign key be something like this?
ALTER TABLE Aircraft
ADD CONSTRAINT fk1 FOREIGN KEY(Model_Number)
REFERENCES Aircraft_Model
Does the same foreign key being referenced from a separate table such as Licence_type need a separate constraint to be added or can it be added from the same one with the same fk1 number?
I was wondering if it was possible to reference a primary key as a
foreign key across 2 or more tables.
If you mean, "Can two or more tables have foreign keys that reference the same column?", then, yes, you can do that. This seems to be what you mean, but it's not what most people mean when they talk about "a foreign key across 2 or more tables".
Declare two different, separate constraints.
ALTER TABLE Aircraft
ADD CONSTRAINT fk1 FOREIGN KEY(Model_Number)
REFERENCES Aircraft_Model (Model_Number);
ALTER TABLE License_Type
ADD CONSTRAINT fk2 FOREIGN KEY(Model_Number)
REFERENCES Aircraft_Model (Model_Number);

Is there any way to make the following sql query work?

I am trying to create two tables using the following SQL:
create table student(sid char(20) primary key,name char(20),age int,hours char(10) references courses(cid));
create table courses(cid char(10),cname char(10),grader char(20) references student(sid));
However I get the following error:
1: ERROR: relation "courses" does not exist
3: ERROR: relation "student" does not exist
Is there any way or syntax which can solve this problem?
You would need to create the tables first (without REFERENCES clause). After that create your foreign keys manually by statement ALTER TABLE mytable ADD CONSTRAINT mytablefk FOREIGN KEY... But first I'd consider if there really is a relationship from table courses to table student!
Rather than creating the Foreign Key constraints at the same time as the tables with the References short-hand, you can add one or both of them afterwards with an Alter Table Add Constraint command. See the Alter Table page in the PostgrSQL manual here.
As mu pointed out, the target of a foreign key has to have a Unique or Primary Key constraint defined, so I've added that on the cid column in the example below.
In your case, it could look something like this:
create table student(sid char(20) primary key,name char(20),age int,hours char(10));
create table courses(cid char(10) primary key,cname char(10),grader char(20));
Alter Table student Add Constraint fk_student_hours_cid Foreign Key (hours) References courses(cid);
Alter Table courses Add Constraint fk_courses_grader_sid Foreign Key (grader) References student(sid);