Create a table containing PK and FK - sql

I am trying to explain what this table does, but unable to see what is happening here. Any suggestion?
CREATE TABLE EMP
(
ID INT NOT NULL PRIMARY KEY,
MGID INT REFERENCES EMP (ID),
NAME VARCHAR(30) NOT NULL
);

It's creating a table called EMP which describes employees. Each employee is identified by a surrogate ID number, has a NAME attribute, and a relationship with a manager identified by MGID.

This code creates a table that's called EMP, with a primary key column called ID of type int, a foreigen key referencing that column called MGID, and a string column called NAME.
Using a foriegn key to the same table enables you to create parent/child relationship for rows in that table.
For instance, if you have an employee that's called Raza, and his manager is calld Far, You will have a row for the manager and a row for Raza and the value of MGID in that row would point to the ID of Far

Assuming that you have some basic knowledge of DBMS, I think you stuck with 'REFERENCES' keyword.
It creates a Parent/Child relationship between ID and MGID.
As you know, the table is for Employee(as the name suggested 'Emp'), Manager is also an employee.
So,before referencing to any employee as a manager it must have entry in table as employee. To perform this kind of validations, 'REFERENCES' keyword can be used.
For example,
ID MGID NAME
1 null a
2 1 b
3 1 c
Above data is valid but,
ID MGID NAME
1 null a
2 3 b
3 1 c
Above data will violate the referential integrity constraints as any employee with ID 3 is not existed yet.
Hope it helps.

Related

Foreign key without correspondence in the referenced table

I'm trying to come up with a solution for an exercise in which I have to create 3 tables: one for employees, one for projects, and one for projects and employees, in which I have to insert the employee's ID and associate with a project ID. In the project_employee table, since it has only 2 columns that reference other tables, I thought I could set them bot as foreign keys, like this:
CREATE TABLE employee_project
(
id_employee numeric FOREIGN KEY REFERENCES employee(id_employee),
id_project numeric FOREIGN KEY REFERENCES project(id_project)
)
Then I stumbled upon a problem: when inserting values on the 3 tables, I noticed that one of the employee's ID number was 4, but on the table employee there was no line with ID 4. Of course, this line wasn't created, but I want to understand: is there a way I could create a line whose ID has no matching record in the referenced table? Could it be a possible mistake in the question, or is there something I'm missing? Thanks in advance for your time!
If there is no rows in employee table with id_employee value 4 then there should not be rows in employee_project table with id_employee value 4. SQL Server will give you an error like below:
The INSERT statement conflicted with the FOREIGN KEY constraint "FK__employee__id__75F77EB0". The conflict occurred in database "test", table "dbo.employee", column 'id_employee'.
But if you want to create employee_project with composite primary key on both the column you can try this:
CREATE TABLE employee_project
(
id_employee int not null,
id_project int not null,
primary key(id_employee, id_project )
)

Storing multiple values in a single column

I have two columns in my table: [Employee_id, Employee_phno].
Employee_id: primary key, data type = int
Employee_phno: allows null, data type = int
Now, how can I insert two phone numbers in the same employee_id?
For example:
employee_id employee_phno()
1 xxxxxxxxx
yyyyyyyyyy
For me, if you want multiple data for column Employee_phno better make another table for Employee_phno. In your second table, set a foreign key as relation for your first table.
Example:
1st table
Employee_id
1
2
3
2nd table
Employee_id Employee_phno
1 1234
2 1512
2 4523
Here you can see the employee with id = 2 has multiple Employee_phno
It is never possible to insert data in such way in single table.
If Employee_id is primary key then you can have only 1 record for an employee.Since you have only one field for Employee_phno,it's not possible to store 2 phone numbers for the same employee.
For doing so, you will have to do any one of the following:
1.Add another column in the data as Employee_Alternate_phno and if all the employees won't have 2 numbers you can make this column allow NULLs.
2.Create another mapping table say EmployeeNumbers where you will have EmployeeId as Foreign key and then the numbers field. Anytime if you want the 2 Employee_phno you can do a join on the mapping table and retrieve the values.

How to reference foreign key from more than one column (Inconsistent values)

I Have table three tables:
The first one is emps:
create table emps (id number primary key , name nvarchar2(20));
The second one is cars:
create table cars (id number primary key , car_name varchar2(20));
The third one is accounts:
create table accounts (acc_id number primary key, woner_table nvarchar2(20) ,
woner_id number references emps(id) references cars(id));
Now I Have these values for selected tables:
Emps:
ID Name
-------------------
1 Ali
2 Ahmed
Cars:
ID Name
------------------------
107 Camery 2016
108 Ford 2012
I Want to
Insert values in accounts table so its data should be like this:
Accounts:
Acc_no Woner_Table Woner_ID
------------------------------------------
11013 EMPS 1
12010 CARS 107
I tried to perform this SQL statement:
Insert into accounts (acc_id , woner_table , woner_id) values (11013,'EMPS',1);
BUT I get this error:
ERROR at line 1:
ORA-02291: integrity constraint (HR.SYS_C0016548) violated - parent key not found.
This error occurs because the value of woner_id column doesn't exist in cars table.
My work require link tables in this way.
How Can I Solve This Problem Please ?!..
Mean: How can I reference tables in previous way and Insert values without this problem ?..
One-of relationships are tricky in SQL. With your data structure here is one possibility:
create table accounts (
acc_id number primary key,
emp_id number references emps(id),
car_id number references car(id),
id as (coalesce(emp_id, car_id)),
woner_table as (case when emp_id is not null then 'Emps'
when car_id is not null then 'Cars'
end),
constraint chk_accounts_car_emp check (emp_id is null or car_id is null)
);
You can fetch the id in a select. However, for the insert, you need to be explicit:
Insert into accounts (acc_id , emp_id)
values (11013, 1);
Note: Earlier versions of Oracle do not support virtual columns, but you can do almost the same thing using a view.
Your approach should be changed such that your Account table contains two foreign key fields - one for each foreign table. Like this:
create table accounts (acc_id number primary key,
empsId number references emps(id),
carsId number references cars(id));
The easiest, most straightforward method to do this is as STLDeveloper says, add additional FK columns, one for each table. This also bring along with it the benefit of the database being able to enforce Referential Integrity.
BUT, if you choose not to do, then the next option is to use one FK column for the the FK values and a second column to indicate what table the value refers to. This keeps the number of columns small = 2 max, regardless of number of tables with FKs. But, this significantly increases the programming burden for the application logic and/or PL/SQL, SQL. And, of course, you completely lose Database enforcement of RI.

Why is a "references" privilege required?

In order to create a FOREIGN KEY Constraint, the <AuthorizationID> that owns the referencing Table must be the current <AuthorizationID> and must have the REFERENCES Privilege on every referenced Column named. Source: https://mariadb.com/kb/en/constraint_type-foreign-key-constraint/
WHY?
The reason for the references privilege is that the table referencing another imposes a constraint on the other table, and the owner of that other table may not be willing to allow that constraint.
Let's see what could happen if there was no references privilege.
CREATE TABLE Employees
(
EmpID INTEGER NOT NULL PRIMARY KEY,
Name VARCHAR(32) NOT NULL,
…
);
INSERT INTO Employees VALUES (1, "Hernandez", …);
Now along comes Joe and creates a table:
CREATE TABLE EmployeeRefs
(
EmpID INTEGER NOT NULL PRIMARY KEY REFERENCES Employees
);
INSERT INTO EmployeeRefs SELECT EmpID FROM Employees;
Now suppose that the HR department needs to let Hernandez go and work elsewhere, and the code knows that the relevant EmpID is 1:
DELETE FROM Employees WHERE EmpID = 1;
This delete fails; the primary key value is still being referenced from the EmployeeRefs table.
This is what is supposed to happen as far as the DBMS is concerned. It was told that values in the EmployeeRefs.EmpID column must match a value in the Employee.EmpID column, and if it deletes Hernandez's record, that won't be true, so it must prevent the deletion (since Joe didn't set up a cascading delete).
Clearly, if any user (with privilege to create tables in the DB) can prevent the HR department from doing its work, there is a problem. The problem is resolved by saying that Joe can only create the reference to the Employee table if he has been given the REFERENCES privilege. And the owner/creator of each table gets to choose who has REFERENCES privilege for the tables that they create.

Weak Entity containing a foreign key as a primary key

I have created a table called STUDENT which consists of Unique ID as the PRIMARY KEY along with other related attributes like Name, Addr, Gender etc....
Since I don't want to increase the table size of the STUDENT, I created a weak entity called ACADEMIC RECORDS which stores the previous Academic Records of the student.But in this table i have only created a PRIMARY KEY Unique ID which references the Unique ID of the student. and there is no other attribute in conjunction with Unique ID in the weak entity ACADEMIC RECORD Table.
As I came across the definition OF A WEAK ENTITY which define its primary key as a combination of weak entity's attribute and the owner's table's primary key(in this case STUDENT)
Is my method of creating a foreign key as the only primary key in the table ACADEMIC RECORD correct??
STUDENT Table
**UID** NAME GENDER ADDRESS PHNO.
ACADEMIC RECORD Table
**UID** HighschoolMarks GradSchoolMarks
There's nothing necessarily wrong with having a primary key that's also entirely a foreign key. It's a common way of implementing something like ‘base classes’, where an entity has a row in a base table, and may have a row in one or more extension tables (one to one-or-zero relationship).
I'm not sure it's the most appropriate schema for what you're doing though. If there really is an exactly one-to-one relationship between academic_records and students, it looks like they are part of the same entity to me.
In which case from a normalisation point of view the record columns should be part of the main students table. Maybe there's an efficiency reason to denormalise, but “I don't want to increase the table size” is not normally an adequate reason. Databases can cope with big tables.
I'm not completely clear on what you are asking, but it sounds like you are using the correct method.
Your STUDENT table requires a primary key to provide a unique reference for each row.
Your ACADEMIC_RECORD table also requires a primary key to provide a unique reference for each row.
Each student may have zero or more academic records, and you want to identify the student to which each academic record belongs. You do this by adding a column in the ACADEMIC_RECORD table which contains the id (the primary key) of the student:
STUDENT ACADEMIC_RECORD
id
id <-------> student_id
name high_school_marks
gender grade_school_marks
address
phone_no
Assume you have three students: Alice, Bob and Dave. Alice and Dave have three academic records, and Bob has two. Your tables would look something like this (I've omitted some columns to make things clearer):
STUDENT
id name
1 Alice
2 Bob
3 Dave
ACADEMIC_RECORD
id student_id
1 1
2 1
3 1
4 2
5 2
6 3
7 3
8 3