Exist foreign key depend 2 primary key? - c#

As question title. Example: i have 3 table employee,teacher,student.
one employee's FOREIGN KEY depend student's PRIMARY KEY
one employee's FOREIGN KEY depend teacher's PRIMARY KEY
I tried but i couldn't.

As I understand your question:
Can 1 Foreign Key refer to 2 different tables?
Answer: No, it cannot.
You can (and probably should) easily define 2 separate foreign keys:
Employee IS|HAS Student
Employee IS|HAS Teacher

You cant have a foreign key linking to two tables.
if you have control over the table structure it might make more sense to have a different structure
table: Person
table: EmployeeInfo (all information about being an employee i.e. EmpNo, ClockNo etc) with a foreign key on Person
table: TeacherInfo (all information about being a teacher i.e. HomeRoom, subject etc) with a foreign key on Person
table: StudentInfo (all information about a student i.e. course, funding type etc) with a foreign key on Person
that way with some simple joins you can get all teachers that are employees, or all students that are employees, or all employees that are neither teachers nor students

One way to do this would be to create a people table that is the parent table and then child tables students, teachers and employees which would have foreign keys from their primary key to the people table. eg:
CREATE TABLE people
(
id bigserial NOT NULL,
first_name character varying(128) NOT NULL,
last_name character varying(128) NOT NULL,
-- other columns appropriate to a person
CONSTRAINT people_pk PRIMARY KEY (id)
)
CREATE TABLE students
(
fk_person bigint NOT NULL,
-- other columns appropriate to the student
CONSTRAINT students_pk PRIMARY KEY (fk_person),
CONSTRAINT students_fk FOREIGN KEY (fk_person)
REFERENCES people (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
CREATE TABLE teachers
(
fk_person bigint NOT NULL,
-- other columns appropriate to the teacher
CONSTRAINT teachers_pk PRIMARY KEY (fk_person),
CONSTRAINT teachers_fk FOREIGN KEY (fk_person)
REFERENCES people (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
CREATE TABLE employees
(
fk_person bigint NOT NULL,
-- other columns appropriate to the employee
CONSTRAINT employees_pk PRIMARY KEY (fk_person),
CONSTRAINT employees_fk FOREIGN KEY (fk_person)
REFERENCES people (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
You could also add a discriminator column to people to allow you to distinguish between students and teachers and a check (or trigger) on the discriminator column in employees to ensure that only teachers and students are put in that table. For more on discriminator columns take a look at the hibernate documents

Related

Can someone explain what a Foreign Key is, and why you use it? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I'm in the middle of learning C# and i'm going towards learning about SQL databases, but i'm not sure i quite understand the Foreign-Key?
Thank you beforehand
A foreign key is another table's primary key. It is used to link the two tables.
Example: we have 2 tables (Person & Employee)
Person has primary key: personID,
Employee has primary key: employeeID
An employee is a person so they have to be linked.
Employee has foreign key: personID
So, for every Employee there is a Person linked to it (where the personID in Employee is the same as the personID in Person).
In the context of relational databases, a foreign key is a field (or collection of fields) in one table that uniquely identifies a row of another table or the same table. In simpler words, the foreign key is defined in a second table, but it refers to the primary key or a unique key in the first table.
This takes us to Primary key. The customers table contains a unique key on each row called customerNumber this is the primary key for the table. On the orders table we have the orderNumber column which is the primary key for that table.
The orders table has a foreign key link back to the customers table though the customer Number. We call the customer Number the foreign key.
Customer Table:
customerNumber CustomerName.
1 Bob
2 Jane
Order table:
OrderNumber customerNumber Status
1 1 Shipped
2 1 Exploded
Using the data above if you wanted to see what orders bob had you would take the primary key being bobs customer id and check the order table for all rows containing the it. This is the foreign key linking two tables.
A FOREIGN KEY is a key used to link two tables together.
A FOREIGN KEY is a field (or collection of fields) in one table that refers to the PRIMARY KEY in another table.
The table containing the foreign key is called the child table, and the table containing the candidate key is called the referenced or parent table.
Reference : https://www.w3schools.com/sql/sql_foreignkey.asp
You use it to link two table together and it makes your data integrity better. You should always use foreign keys to link table references, unless you have clear reason not to.
Let's say you have Foobar table with UserId column and User table with Id column. You use foreign key to link UserId column from Foobar table to User table's Id column.
After that if you have Foobar row with UserId of 1 and try to delete row from User that has Id column value of 1 you get an error because Foobar references it. Also inserts are validated, let's say you try to insert row to Foobar table with UserId that doesn't exists in User table and you'll get an error as well.

Asp.Net Core Entity Framework Migration Error: index needed in a foreign key constraint [duplicate]

I need to ALTER my existing database to add a column. Consequently I also want to update the UNIQUE field to encompass that new column. I'm trying to remove the current index but keep getting the error MySQL Cannot drop index needed in a foreign key constraint
CREATE TABLE mytable_a (
ID TINYINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Name VARCHAR(255) NOT NULL,
UNIQUE(Name)
) ENGINE=InnoDB;
CREATE TABLE mytable_b (
ID TINYINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Name VARCHAR(255) NOT NULL,
UNIQUE(Name)
) ENGINE=InnoDB;
CREATE TABLE mytable_c (
ID TINYINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Name VARCHAR(255) NOT NULL,
UNIQUE(Name)
) ENGINE=InnoDB;
CREATE TABLE `mytable` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`AID` tinyint(5) NOT NULL,
`BID` tinyint(5) NOT NULL,
`CID` tinyint(5) NOT NULL,
PRIMARY KEY (`ID`),
UNIQUE KEY `AID` (`AID`,`BID`,`CID`),
KEY `BID` (`BID`),
KEY `CID` (`CID`),
CONSTRAINT `mytable_ibfk_1` FOREIGN KEY (`AID`) REFERENCES `mytable_a` (`ID`) ON DELETE CASCADE,
CONSTRAINT `mytable_ibfk_2` FOREIGN KEY (`BID`) REFERENCES `mytable_b` (`ID`) ON DELETE CASCADE,
CONSTRAINT `mytable_ibfk_3` FOREIGN KEY (`CID`) REFERENCES `mytable_c` (`ID`) ON DELETE CASCADE
) ENGINE=InnoDB;
mysql> ALTER TABLE mytable DROP INDEX AID;
ERROR 1553 (HY000): Cannot drop index 'AID': needed in a foreign key constraint
You have to drop the foreign key. Foreign keys in MySQL automatically create an index on the table (There was a SO Question on the topic).
ALTER TABLE mytable DROP FOREIGN KEY mytable_ibfk_1 ;
Step 1
List foreign key ( NOTE that its different from index name )
SHOW CREATE TABLE <Table Name>
The result will show you the foreign key name.
Format:
CONSTRAINT `FOREIGN_KEY_NAME` FOREIGN KEY (`FOREIGN_KEY_COLUMN`) REFERENCES `FOREIGN_KEY_TABLE` (`id`),
Step 2
Drop (Foreign/primary/key) Key
ALTER TABLE <Table Name> DROP FOREIGN KEY <Foreign key name>
Step 3
Drop the index.
If you mean that you can do this:
CREATE TABLE mytable_d (
ID TINYINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Name VARCHAR(255) NOT NULL,
UNIQUE(Name)
) ENGINE=InnoDB;
ALTER TABLE mytable
ADD COLUMN DID tinyint(5) NOT NULL,
ADD CONSTRAINT mytable_ibfk_4
FOREIGN KEY (DID)
REFERENCES mytable_d (ID) ON DELETE CASCADE;
> OK.
But then:
ALTER TABLE mytable
DROP KEY AID ;
gives error.
You can drop the index and create a new one in one ALTER TABLE statement:
ALTER TABLE mytable
DROP KEY AID ,
ADD UNIQUE KEY AID (AID, BID, CID, DID);
A foreign key always requires an index. Without an index enforcing the constraint would require a full table scan on the referenced table for every inserted or updated key in the referencing table. And that would have an unacceptable performance impact.
This has the following 2 consequences:
When creating a foreign key, the database checks if an index exists. If not an index will be created. By default, it will have the same name as the constraint.
When there is only one index that can be used for the foreign key, it can't be dropped. If you really wan't to drop it, you either have to drop the foreign key constraint or to create another index for it first.
Because you have to have an index on a foreign key field you can just create a simple index on the field 'AID'
CREATE INDEX aid_index ON mytable (AID);
and only then drop the unique index 'AID'
ALTER TABLE mytable DROP INDEX AID;
I think this is easy way to drop the index.
set FOREIGN_KEY_CHECKS=0; //disable checks
ALTER TABLE mytable DROP INDEX AID;
set FOREIGN_KEY_CHECKS=1; //enable checks
drop the index and the foreign_key in the same query like below
ALTER TABLE `your_table_name` DROP FOREIGN KEY `your_index`;
ALTER TABLE `your_table_name` DROP COLUMN `your_foreign_key_id`;
Dropping FK is tedious and risky. Simply create the new index with new columns and new index name, such as AID2. After the new Unique Index is created, you can drop the old one with no issue. Or you can use the solution given above to incorporate the "drop index, add unique index" in the same alter table command. Both solutions will work
In my case I dropped the foreign key and I still could not drop the index. That was because there was yet another table that had a foreign key to this table on the same fields. After I dropped the foreign key on the other table I could drop the indexes on this table.
If you are using PhpMyAdmin sometimes it don't show the foreign key to delete.
The error code gives us the name of the foreign key and the table where it was defined, so the code is:
ALTER TABLE your_table DROP FOREIGN KEY foreign_key_name;
You can show Relation view in phpMyAdmin and first delete foreign key. After this you can remove index.
You can easily check it with DBeaver. Example:
As you can see there are 3 FKs but only 2 FK indexes. There is no index for FK_benefCompanyNumber_beneficiaries_benefId as UK index provide uniqueness for that FK.
To drop that UK you need to:
DROP FK_benefCompanyNumber_beneficiaries_benefId
DROP UK
CREATE FK_benefCompanyNumber_beneficiaries_benefId
The current most upvoted answer is not complete.
One needs to remove all the foreign keys whose "source" column is also present in the UNIQUE KEY declaration.
So in this case, it is not enough to remove mytable_ibfk_1 for the error to go away, mytable_ibfk_2 and mytable_ibfk_3 must be deleted as well.
This is the complete answer:
ALTER TABLE mytable DROP FOREIGN KEY mytable_ibfk_1;
ALTER TABLE mytable DROP FOREIGN KEY mytable_ibfk_2;
ALTER TABLE mytable DROP FOREIGN KEY mytable_ibfk_3;
Its late now but I found a solution which might help somebody in future.
Just go to table's structure and drop foreign key from foreign keys list. Now you will be able to delete that column.

Add a field to a relation table and access row values through code

Using EF code first and Fluent, I've created two tables containing data and a third table which is the "relation table" (not sure what the 'official' word for it is?). Each row holds Id's from both tables and defines a many-to-many relation between the two.
The tables hold purchase orders and products. Now I need to specify the amount of products in a purchase order as well, so my most logical conclusion was to add a field in the relation table that specifies the quantity, so that the table will become:
orderId | productId | quantity
83923 | 867392 | 100
83923 | 865392 | 250
83923 | 323392 | 50
Is this possible using EF code first? I couldn't find a way, but it's hard to search for a solution since I find it hard to concisely describe what I need to do.
I thought I could add a field using the designer, which works, but I have no idea how to access the value through code now.
My tables:
The field/table names are all in Dutch, but hopefully it's understandable & readable.
-- Purchase orders
CREATE TABLE [dbo].[InkoopOrders] (
[InkoopOrderId] INT IDENTITY (1, 1) NOT NULL,
[Kenmerk] NVARCHAR (MAX) NULL,
CONSTRAINT [PK_dbo.InkoopOrders] PRIMARY KEY CLUSTERED ([InkoopOrderId] ASC)
);
-- Products
CREATE TABLE [dbo].[Artikelen] (
[ArtikelId] INT IDENTITY (1, 1) NOT NULL,
[Kenmerk] NVARCHAR (MAX) NULL,
CONSTRAINT [PK_dbo.Artikelen] PRIMARY KEY CLUSTERED ([ArtikelId] ASC)
);
-- Relation table
CREATE TABLE [dbo].[InkoopOrderArtikel] (
[InkoopOrderId] INT NOT NULL,
[ArtikelId] INT NOT NULL,
CONSTRAINT [PK_dbo.InkoopOrderArtikel] PRIMARY KEY CLUSTERED ([InkoopOrderId] ASC, [ArtikelId] ASC),
CONSTRAINT [FK_dbo.InkoopOrderArtikel_dbo.InkoopOrders_InkoopOrderId] FOREIGN KEY ([InkoopOrderId]) REFERENCES [dbo].[InkoopOrders] ([InkoopOrderId]) ON DELETE CASCADE,
CONSTRAINT [FK_dbo.InkoopOrderArtikel_dbo.Artikelen_ArtikelId] FOREIGN KEY ([ArtikelId]) REFERENCES [dbo].[Artikelen] ([ArtikelId]) ON DELETE CASCADE
);
This was achieved through creating the two models, and defining the relation in Fluent:
modelBuilder.Entity<InkoopOrder>()
.HasMany(o => o.Artikelen)
.WithMany(a => a.InkoopOrders)
.Map(
m => {
m.MapLeftKey("InkoopOrderId");
m.MapRightKey("ArtikelId");
m.ToTable("InkoopOrderArtikel");
}
);
In EF, in may to many relationships, the association table can only have the Key columns of the related tables. So, no, you cannot do that with a many to many using EF. If you wanted to do this, you'd need to specify two one-to-may relationships (from both many to many tables, to the association table). Look at this SO answer for a full explanation.
However, I don't understand why you want to use a many to many. You simply need to use the classical Order table with a child OrderDetail table that has the ProductId, UnitPrice, Units, Total, and so on. Forget about using the many to many for this case. It's much easier in this way.

Manual Entity Framework association

I have the following tables:
Table Group (
id INT PK,
year INT PK,
name VARCHAR
)
Table Person (
id PK,
GroupID INT,
name VARCHAR
)
The database does not have foreign keys defined so I want to create a manual association from the Person tables GroupID to the Group tables id.
To do this I right click Person and Add an association. I create a Many to One association and everything works. The problem is when I go to add the mapping. Because the Group table has two primary keys entity framework was something from the Person table to map to the year key.
What do I need to do to create the association?
You cannot create such association because EF follows same rules as database. All PK columns from principal entity must exists as FK columns in dependent entity.
The only way can be some database view selecting distinct Groups with Id and Name and mapped as read only entity and build navigation between those two. I didn't try it but I guess it should work. It will have its own disadvantages because you will have two completely unrelated entities for group and the entity related to person will not accept any modification (without mapping custom SQL commands or stored procedures to insert, updated and delete operations).

SQL value contrains to another table data

I have a couple of tables, lets say I have a cars table and I have another table which hold all types of cars available(just to avoid multiple entries on the cars table) so I want a constraint on my cars table that has a "list/set" of types of cars FROM the TypesOFCar Table this table contains (Make, Model, etc..) how can I archive this.
I want it modular so I can just add another kind of car to the TypeOfCar table and it becomes available on the Cars table, thx in advance.
The best way to implement this would be through a foreign key constraint. Essentially, you derive your tables such like:
CREATE TABLE dbo.CarType
(
[Id] INT NOT NULL DEFAULT(1, 1),
[Description] VARCHAR(255) NOT NULL
CONSTRAINT PK_CarType PRIMARY KEY NONCLUSTERED ([Id])
)
CREATE TABLE dbo.Car
(
[Id] INT NOT NULL DEFAULT(1, 1),
[Registration] VARCHAR(7) NOT NULL,
[CarType_Id] INT NOT NULL
CONSTRAINT PK_Car PRIMARY KEY NONCLUSTERED ([Id]),
CONSTRAINT FK_Car_CarType_Id FOREIGN KEY ([CarType_Id]) REFERENCES dbo.CarType ([Id])
)
In those example tables, I create a foreign key constraint that maps the CarType_Id column of the Car table to the Id column of the CarType. This relationship enforces that a CarType item must exist for the value being specified in the Car table.
You want to add a CarType column to your Cars table and make it a foreign key to your TypeOfCar table.

Categories