I'm a learner and trying to create 1 to many relationship between two tables:
Emp(eid, ename, designation) where eid is primary key and table pay(desigId, designation, salary) where desigId is primary key. On enforcing referential integrity and creating relationship, I'm getting message ms access can't create this relationship and enforce referential integrity. Data in table Emp violates integrity rules. For example, there may be records relating to employee in the related table, but no record for employee in the primary table.
It seems like you have data that violates the relationship you want to build. to find the invalid data run this sql
SELECT pay.eid
FROM pay LEFT JOIN Emp ON pay.eid = Emp.eid
WHERE Emp.eid Is Null
Related
Say I want to create 2 tables.
Table A has student_id, student_name, student_address and Table B has student_id, student_marks.
While creating these two tables is there any other way to establish the relationship between these 2 tables without using foreign key concept in oracle Database or any other database generally?
You can join tables on any keys you like -- assuming the comparison logic is syntactically correct. They do not have to be declared as foreign keys.
The purpose of foreign keys is to maintain data integrity. You cannot put a student_id in B that is not in A. If you don't care about that, or don't understand it, or don't need it, then there is no need to declare the foreign key relationship.
Whether or not it is declared, you can still join the tables.
I have an employee table with the following columns:
fname (varchar), lname (varchar), id (numeric)
id is the primary key.
There is a table name called works_on with columns
projectname (varchar), id (numeric)
Here, id is a foreign key that references the employee table.
When I was trying delete a row from the employee table like this:
delete from employee where id = 1
I get this error:
update or delete on table "employee" violates foreign key constraint "works_on_id_fkey" on table "works_on"`.
I am new to the database management system.
Any solution?
As employee is a foreign key in table works_on; the reason you are unable to delete employee ID 1 is because employee ID 1 exists on works_on (or perhaps other tables in which employee is a foreign key). The system is trying to maintain integrity of the database by preventing you from deleting an employee affiliated with works_on.
Say the system let you delete the employee record. Now when you look at the works_on table what would employee 1 relate to? You can no longer look up first/last names among other information. So the system is saying: If you want to delete the employee record, you must first remove/alter the foreign key associations to other system records; to ensure their continued integrity. If the system let you do this it would be called "Orphaning" a record. the parent record to which the child associates no longer exists.
To resolve a few options are:
Create a procedure that deletes employees but first checks any tables in which employee is a foreign key and ensures it's ok to delete those as well; and then deletes those records before deleting the employee record. (this can cause a massive daisy chain if those tables have PK's to which other tables are FK. But that's the nature of RDBMS.
Create a feature that lets you assign such records to employee 1's replacement or removes such records if no longer relevant.
enable ON DELETE CASCADE ON UPDATE CASCADE, which will automatically delete child records if parent record is deleted. (BE VERY CAREFUL AND CONSIDER how this impacts your system before enabling) Example: Docs
Don't delete the record, instead maintain a status field showing active/inactive and use it as a control mechanism to show or not show employees and their associated records.
There's several other options to consider as well; you must ask yourself, or the business for which this is being developed, what should happen to all those records in which employee 1 is a foreign key. Delete some/All, reassign some delete some? Prompt the user for how they want to handle each instance? Simply Inform the user they must first address the constraints found in (List all places this employee has a FK relationship?) and ensure they have a way to handle all those places... Lots of options.
You can not delete a row by that way. Because it has the constraint id in it (works_on_id_fkey). If you want to delete, you have to remove constraint from it.
alter table employee drop foreign key works_on_id_fkey
Just curious if I can have the same primary key in 3 different tables? I am going to create an Employee, FullTime and PartTime tables. I would like to make an EmployeeID the primary key for all 3. Any thoughts?
You can have the primary key EmployeeId in a table called Employees. This would have common information, such as date of hire and so on.
Then, each of your subtables can have an EmployeeId that is both a primary key in the table and a foreign key reference to Employees.EmployeeId. This is one way to implement a one-of relationship using relational tables.
Unfortunately, unless you use triggers, this mechanism doesn't prevent one employee from being in the two other tables, but that is not part of your question.
It sounds like your design is wrong.
The entity is the employee
An attribute of an employee is their [current^] employment status.
Therefore, in its simplest form, you need a single employee table, with a column that indicates their status.
To improve this further, the employee status column should have a foreign key relationship with another table that stores the possible employee statuses.
^ current status is a 1:1 relationship. If you wanted the history of changes, this is a 1:M and needs modelling differently.
I have difficulty to optimizing the database design in a situation
There is a table with 3000 employees and another one table with 300 departments.
Problem is there is a possibility to 3000 employees in 300 departments. Basically each employee will work in all department 300x3000 records (worse case). May be only 10 employees will work in 300 department (best case) and not a problem or have a composite table.
So what is the best way to structure
Please advice me
Thanks
In a relational database, the appropriate pattern for this is to store the fact that an employee works in a department is a relation:
create table employees(employee_id, ..., primary key(employee_id));
create table departments(department_id, ..., primary key(department_id));
create table works_in(
employee_id,
department_id,
primary key(employee_id, department_id),
foreign key(employee_id) references employees(employee_id),
foreign key(department_id) references departments(department_id)
);
/* Add column datatypes as needed */
This pattern is applicable in almost all cases, even for large relationship tables. If you are worried about space consumption, many databases can store this kind of table very efficiently, e.g., storing them physically as an index-organized table, e.g., storing them grouped by employee_id, etc.
However, even 300 x 3000 entries does not sound as if you would need such kind of physical database design optimization.
What kind of sql tricks you use to enter data into two tables with a circular reference in between.
Employees
EmployeeID <PK>
DepartmentID <FK> NOT NULL
Departments
DepartmentID <PK>
EmployeeID <FK> NOT NULL
The employee belongs to a department, a department has to have a manager (department head).
Do I have to disable constraints for the insert to happen?
I assume your Departments.EmployeeID is a department head. What I'd do is make that column nullable; then you can create the department first, then the employee.
Q: Do I have to disable constraints for the insert to happen?
A: In Oracle, no, not if the foreign key constraints are DEFERRABLE (see example below)
For Oracle:
SET CONSTRAINTS ALL DEFERRED;
INSERT INTO Departments values ('foo','dummy');
INSERT INTO Employees values ('bar','foo');
UPDATE Departments SET EmployeeID = 'bar' WHERE DepartmentID = 'foo';
COMMIT;
Let's unpack that:
(autocommit must be off)
defer enforcement of the foreign key constraint
insert a row to Department table with a "dummy" value for the FK column
insert a row to Employee table with FK reference to Department
replace "dummy" value in Department FK with real reference
re-enable enforcement of the constraints
NOTES: disabling a foreign key constraint takes effect for ALL sessions, DEFERRING a constraint is at a transaction level (as in the example), or at the session level (ALTER SESSION SET CONSTRAINTS=DEFERRED;)
Oracle has allowed for foreign key constraints to be defined as DEFERRABLE for at least a decade. I define all foreign key constraints (as a matter of course) to be DEFERRABLE INITIALLY IMMEDIATE. That keeps the default behavior as everyone expects, but allows for manipulation without requiring foreign keys to be disabled.
see AskTom: http://www.oracle.com/technology/oramag/oracle/03-nov/o63asktom.html
see AskTom: http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:10954765239682
see also: http://www.idevelopment.info/data/Oracle/DBA_tips/Database_Administration/DBA_12.shtml
[EDIT]
A: In Microsoft SQL Server, you can't defer foreign key constraints like you can in Oracle. Disabling and re-enabling the foreign key constraint is an approach, but I shudder at the prospect of 1) performance impact (the foreign key constraint being checked for the ENTIRE table when the constraint is re-enabled), 2) handling the exception if (when?) the re-enable of the constraint fails. Note that disabling the constraint will affect all sessions, so while the constraint is disabled, other sessions could potentially insert and update rows which will cause the reenable of the constraint to fail.
With SQL Server, a better approach is to remove the NOT NULL constraint, and allow for a NULL as temporary placeholder while rows are being inserted/updated.
For SQL Server:
-- (with NOT NULL constraint removed from Departments.EmployeeID)
insert into Departments values ('foo',NULL)
go
insert into Employees values ('bar','foo')
go
update Departments set EmployeeID = 'bar' where DepartmentID = 'foo'
go
[/EDIT]
This problem could be solved with deferable constraints. Such constraints are checked when the whole transaction is commited, thus allowing you to insert both employee and department in the same transaction, referring to each other. (Assuming the data model makes sense)
Refactor the schema by removing the circular reference.
Delete an ID column from either of the table schema.
Departments.EmployeeID doesn't seem to belong there in my opinion.
I can't think of a non hackish way to do this. I think you will need to remove the constraint or do some type of silly dummy values that get updated after all the inserts.
I'd recommend refactoring the DB schema. I can't think of any reasons why you would want it to work this way.
Maybe something like, Employee, EmployeeDepartment (EmployeeId, DepartmentId) and Department would be a better way to accomplish the same goal.
You could create a row in the Department table for 'Unassigned'
To create a new department with a new Employee you then would
Create the Employee (EmployeeA) in the 'Unassigned' Department
Create the new department (DepartmentA) with the employee EmployeeA
Update EmployeeA to be in DepartmentA
This wouldn't invalidate your current schema, and you could set up a task to be run regularly to check there are no members of the Unassigned department.
You would also need to create a default employee to be the Employee of Unassigned
EDIT:
The solution proposed by chaos is much simpler though
There are a few good designs I've used. All involve removing the "manager" EmployeeID from the Department table and removing the DepartmentID from the Employee table. I've seen a couple answers which mention it, but I'll clarify how we used it:
I typically end up with an EmployeeDepartment relationship link table - many to many, usually with flags like IsManager, IsPrimaryManager, IsAdmin, IsBackupManager etc., which clarify the relationship Some may be constrained so that there is only one Primary Manager allowed per department (although a person can be a PrimaryManager of multiple departments). If you don't like the single table, then you can have multiple tables: EmployeeDepartment, ManagerDepartment, etc. but then you could have situations where a person is a manager but not an employee, etc.
We also typically allowed people to be members of multiple departments.
For simplified access, you can provide views which perform the join appropriately.
Yes, in this instance you will have to disable a foreign key.
You need to get rid of one or the other reference permanently . This is not a viable design structure. Which has to be entered first? Department or Employee? Unless your departments are all one employee big, the structure doesn't make sense anyway as each employee would have to have a distinct departmentid.