Trigger to enforce M-M relationship - oracle

Suppose I have following schema :
DEPARTMENT (DepartmentName, BudgetCode, OfficeNumber, Phone)
EMPLOYEE (EmployeeNumber, FirstName, LastName, Department, Phone, Email)
The problem am facing is how to design a system of triggers to enforce the M-M relationship.Assuming that departments with only one employee can be deleted. Also I need to assign the last employee in a department to Human Resources.
I have no idea to enforce M-M relationship through trigger. Please help

Many-to-many conditions should not be enforced using a trigger. Many-to-many conditions are enforced by creating a junction table containing the keys in question, which are then foreign-keyed back to the respective parent tables.
If your intention is to allow many employees to be in a department, and to allow an employee to be a member of many departments, the junction table in question would look something like:
CREATE TABLE EMPLOYEES_DEPARTMENTS
(DEPARTMENTNAME VARCHAR2(99)
CONSTRAINT EMPLOYEES_DEPARTMENTS_FK1
REFERENCES DEPARTMENT.DEPARTMENTNAME,
EMPLOYEENUMBER NUMBER
CONSTRAINT EMPLOYEES_DEPARTMENTS_FK2
REFERENCES EMPLOYEE.EMPLOYEENUMBER);
This presumes that DEPARTMENT.DEPARTMENTNAME and EMPLOYEE.EMPLOYEENUMBER are either primary or unique keys on their respective tables. Get rid of the column EMPLOYEE.DEPARTMENT as it's no longer needed. Now by creating rows in the EMPLOYEES_DEPARTMENTS table you can relate multiple employees with a department, and you can relate a single employee with multiple departments.
The business logic requiring that only departments with one or fewer employees can be deleted should not be enforced in a trigger. Business logic should be performed by application code, NEVER by triggers. Putting business logic in triggers is a gatèw̢ay to unending debugging sessions. M̫̣̗̝̫͙a̳͕̮d̖̤̳̙̤n̳̻̖e͍̺̲̼̱̠͉ss̭̩̟ lies this way. Do not give in. Do not surrender. ̬̦B҉usi͢n̴es̡s logic ̶in triggers opens deep wounds in the fabric of the world, through which unholy beings of indeterminate form will cross the barrier between the spheres, carryi͞n̨g o̡f͠f t͢h̶e ̕screaming͡ sou͏ĺs o͜f͜ ̢th͜e̴ ̕de͏v́e̡lop͏e͜r͝s to an et͞er͜n̸it̶y ́of͢ pain̶ ąn̨d͢ ̨to͟r̨ment͟. Do not, as I have said, put b́u͜siness͞ ̸log̛i͘ç ̵in͢ ͞trigge͠rs͞.̡ Be firm. Resist.You must resist. T̷he ̢Tem͟p͞t̶at͏i͝o̶n҉s͘ ̢m͘a̶y ́śing hymns̷ ́o͢f̴ ̸un͘hol̵y r̶ev͢ęla͠t̡ion̴ ͢buţ ́yo͠u̵ mu͏s͝t ͝n͜͏͟o҉t̶͡͏ ̷l̸̛͟͢ì̧̢̨̕s̵̨̨͢t̵̀͞e̶͠n̶̴̵̢̕. Only by standing firmly in the door between the worlds and blocking out the hideous radiance cast off by bú̧s̷i̶̢n̵̕e̵ş͝s ́l̴ó̢g̛͟i̕͏c i͞n̕ ͏t̵͜r͢͝i̸̢̛ģ͟ge̸̶͟r̶s͢͜, which perverts the very form of the world ąnd̴̀͝ ç͞a̧͞l̶l͟͜s̕͘͢ Z̶̴̤̬͈̤̬̲̳͇ͯ̊ͮ͐̒̆͂͠Â̆́̊̓͛́̚͏̮̘̗̻̞̬̱ͅL̛̄̌͏̦͕̤͎̮̦G̷͖̙̬͛̇ͬ̍͒̐̅O̡̳͖͎̯̯͍ͫ̽ͬ͒͂̀ i͜҉nt͝ǫ̴ ̸b̷͞è͢ì̕n̴g͏,̛̀͘ ̴c҉á̴͡ń ̀͠youŕ̨ ̧̨a̸p͏̡͡pl̷͠ic͞a̢t̡i͡҉ǫn̴ ̸s̶͜u̶͢ŗv̛í̴v́ȩ.͘͘ Resist. R͏͢͝e͏͢͟s̸͏͜ì̢̢s͠ţ̀. T̶̀h̨̀e̶r̀͏e͢͞ ̶i̶̡͢s̴ ͞͞n̵͝o̡ ́ẁ҉̴a̡y̕҉ ̶b́͏u̵̶̕t͜ ̨s͘͢t͘͠į͟l͘l̷̴ ̴͜͜ỳò͜u҉̨ ̨͏mus̸͞t̸̛͜ ̧rȩ̴s̢͢i͘͡s͏t̸.̛̀͜ Your very śo͡u̧̧͘ļ͟͡ is compromised by p͝u͘͝t̢͜t͠i̸ņ̸̶g͟͡ ̵̶̛b̴҉u̶̡̨͜͞s̷̵̕͜͢i͝҉̕͢ǹ͏e̡͞ś̸͏ş̕͜͡҉ ̴̨ĺ̵̡͟͜o̶̕g͠i͢͠c̕͝ ̕͞i̧͟͡n̡͘͟ ̶̕͞t̡͏͟҉̕r̸̢̧͡͞i̴̡͏̵͜g̵̴͟͝ģ̴̴̵ę̷̷͢r̢̢ś̸̨̨͜. T̀͜͢o̷͜ny̕ ͟͡T̨h̶̷̕e ̢͟P̛o̴̶n͡y shall rise from his dark stable and d͞ę̡v̶̢ó͟u̸̸r̴͏ ̷t͞h̀e̛ ̨͜s̷o̧͝u҉l̀ ͟͡o͢͏f̵͢ ̛t͢h̶̛e̢̢ ̡̀vi͜͞r̢̀g̶i̢n͞, and yet y͢ơú͝ m̷̧u͏s͡t̡͠ ̛s̷̨t̸̨i̴̸l̶̡l ͝ǹot̵ ͞p̧u̵t̨ ͜͏b̀̕u̕s̨í̵ņ̀͠ȩs̵͟s ́͞l̛҉o̸g̨i̴͟c ͘͘i͘nt̛o͡ ͘͘͞t̶͞r̀̀i̕ǵ̛g̵̨͞e̸͠҉r̵͟ś! It is too much to bear, we cannot stand! Not even the children of light may put business logic into their triggers, for b̴̸̡̨u͜͏̧͝ş̶i̷̸̢̛҉ń̸͟͏́e̡͏͏͏s̷̵̡s̕͟ ͏̴҉͞l̷̡ǫ̷̶͡g҉̨̛i͘͠͏̸̨c̕͢͏ ̸̶̧͢͢i̸̡̛͘n͢͡ ̀͢͝t̷̷̛́ŗì̴̴̢g̶͏̷ǵ͠ȩ̀́r̸̵̢̕͜s͞͏̵ is the very es̵s̕͡ę̢n͞c̨e̢͟ ̴o̶̢͜f͏ ͟d́ar͟͞͠k̡͞n̢̡es̵̛͡s̀̀͡ and dev͘ou͝͡r̨̡̀s͢͝ ҉͝t҉h̴e̡͘ l̫̬i̤͚ͅg̞̲͕̠͇̤̦̹h̩̙̘̭̰͎͉̮̳t͙̤̘̙! Yea, yea, the blank-faced ones rì͢s̨͘e from the f͟͢͏o̵͜͝n̶t̨ ̵o͏f̸̡͠ ͏͝fl͟͞a̵̷҉me̶̵͢ and ca͝s͜t́ down the p̹̤̳̰r̮̦̥̥̞̫͑͂ͤ͑ͮ͒̑ï̄̌ͬͨe̦̗͔ͥͣ̆̾̂s̬̭̮̮̜ͭt̻̲̍sͫͣ̿ ̐͗̈ͤ͂ͦ̅f̭͚̪̻̣̩ͮ̒ṟͨ͌ͮ̅̓ỏ̝͓̝̣̟̼m̳͇̱̝͔͒ ͒ͫͧ͂̓̈̈́t̲̔̅̎͐h̺͈͍ͣͧ̿ē̪̼̪̻͉̪̙̐̽̎̉i̠͎̗͕̗̣̬̐̎͛r͓̫͌ͅ ̼a͑̈ͯͦ̍l̪͉͖̥͚̤͌ͨ͊ͦͤ̔t̫͎̹ͯa̼̻͍̳̟̤̬̓ͪ̀r̭͖̓ͬ̉̉ͤ͊ṡ̐ͪ̊̋̄̅! A̵̵̛v͝é͜ŕt̶͏ ̶y̸͝͠o̶u̧͘r͏̡ ̧e͞y҉e̕͝s,̀ ͡t̛h̛o̢͞ug̸̢h̵͟ ̡y̷o͢҉͢u̧͡ ̕͡c҉̵̶an͠͏n҉o̧͢t!̸̨͘ ͡H̵e̸͢͡ ̧̕c̶ơm̷̢̢e̶͞ś͢!̨́ ̷H̕ȩ ̵c̨̡͟o̴҉m̷͢es͠!̷͘͞ P̱̼̯̟͈h̝̳̞̖͚'͉̙͉̰̲̺n̪̦͕̗͜g͔̹̟̰̰̻̩l̬͈̹̥͕͖ͅụ̻̺̤̤̬̳i̸̯̬̝̻̣͚̫ ̰̹̞̞m͟g̷̝͓͉̤l̩͇̙͕w̪̦̰͔'̮̟̱̀n̢̜a̦f̘̫̤̘̬͓̞h̠͍͖̯ͅ ̩̠͓̯̘̫C̟̘̗̘͘ṭ͍͕ͅh̤ͅu̼̦̘̥ͅl҉̦hu̠̤̤̘͚ ̘̕R̶̟'̠͔̞̻͇l̩̺̗̻͖͓̕ͅy̛̖ȩ͉̭̖ẖ̡̥̼͈̖ w̟̫̮͇͔͞ͅg͈̘̱̻a̰͟h̘͙͖͢'̮̲̯͞n̤̜͍̯̳a͓͓̲̲g̱̻͈ĺ͍ ̷̣̞̲͖͍̲̺f̲ͅh͇͕̪̘͟t͔͈̙a͓͢g҉̳̜̲͚n͓͚͎̱̠̜!
Don't ask me how I know.
Best of luck.

Related

Database: Storing multiple Types in single table or multiple intermediate tables for Delta Tables

Using Java and Oracle.
We need to update changes in Email, UserID of employee to third party.
Actual table is Employee and intermediate table we keep which we will use for comparison of changes before sending to third party.
Following are database designs coming in mind for intermediate table:
Only Single table:
EmployeeiD|Value|Type|UpdateDate
Value is userid or email, type will be 'email' or 'userid'. Update date is kept so to figure out that which of email or userid was different and update to third party.
Multiple Table:
Employee_EmailID
EmpId|EmailID|Updatedate
Employee_UserID
EmpId|UserID|Updatedate
Java flow will be:
Pick employee from actual table.
Pick employee from above intermediate table.
Compare differences. Update difference to third party.
Update above table with updated value and last update date.
Which one is consider as best way, single table approach or multiple table or is there any standard way to implement the same? There are 10,000 Employees in system.
Intermediate table is just storing Delta records i.e Records transferred to third party so that it can be compared next day.
Good database design has separate tables for different concepts. Using the same database column to hold different types of data will lead to code which is harder to understand, prone to data corruption and less performative.
You may think it's only two tables and a few tens of thousands of rows, so does it matter? But that is only your current requirement. What you choose now will set the template for what happens when (say) you need to add telephone numbers to the process.
Now in future if we get 5 more entities to update
Do you mean "entities", like say Customers rather than Employees? Or do you really mean "attributes" as in my example of Employee Telephone Number?
Generally speaking we have a separate table for distinct entities, and all the attributes of that entity are grouped at the same cardinality. To take your example, I would expect an Employee to have one UserID and one Email Address so I would design the table like this:
Employee_audit
EmpId|UserID|EmailID|Updatedate
That is, I have one record which stores the complete state of the Employee record at the Updatedate.
If we add a new entity, Customers then we have a new table. Simple. But a new attribute like Employee Phone Number offers a choice, because an employee can have more than one: work landline, mobile, fax, home, etc. So we could represent this in three ways: a child table with a type column, multiple child tables for each type, or as distinct columns on the Employee record.
For the main Employee table I would choose the separate table (or tables, depending on whether I'm shooting for 6NF). But for an audit table I would choose one record per Employee and pivot the phone numbers like this:
Employee_audit
EmpId|UserID|EmailID|Landline|Mobile|Fax|Home|Updatedate
The one thing I would never do is have a single table with type and value columns. It seems attractive because it means we could track additional entities without any further DDL. But in fact it becomes harder to re-assemble the complete state of an Employee at any given time with each attribute we add. Also it means the auditing process itself is more complicated (because it needs to determine which attributes have changed and whether it needs to audit the change) and more expensive (because changing three attributes on the same record entails inserting three audit records).

Multiple relationships on a table

SQL Server 2012 MVC3 EF4.3.1 Code First project.
I have a Teacher and Student table with a one to many relationship. The Teacher’s tables Id will be used as the account number so its Id numbering needs to be separate from the Student’s. I would like to create a Person table (containing shared properties such as First, Last, Phone, Email) to reduce redundancy on the properties. Person will also have a one to many relationship to an Address table.
I’ve thought of trying a Table per Hierarchy model with Teacher and Student inheriting from Person but then the Id sets would not be separate and I would have to have a one to many relationship internally on the Person table. I could generate the ID’s through code but is an internal one to many doable or practical?
Another scenario would be to setup Person as a child table with a one to one between and Teacher and Person and a one to one between Student and Person but I’m not sure how or if it’s possible to have two separate one to one’s on a table.
Is there a practical way to do what I want or should I not worry about the redundancy and not use a Person table? If I went that route would it be possible to have two separate one to many relationships to an Address table (Teacher-Address and Student-Address)? Or for that matter a one to many (Teacher-Address, teacher may have an additional shipping address) and one to one (Student-Address)?
Thank you
Another way to do it is to have a one to one between a Person and a Role table. Teacher and Student are merely roles in this arrangement. A given Role can be fulfilled by many Person instances.
You could also do a Person table with an IsTeacher flag.
I can see two possibilities:
One: Go with your Student and Teacher inheriting from a base table of Person and not worry about the 'redundancy'. It's not a redundancy because your relating a Student and a Teacher not a Person to a Person and so in your database and DOM the Person table and Person class know nothing of the Teacher to Student relationship, it only knows that its a person. The teacher and student relationships are stored in there respective types, not the person type. Also, look at Table per Type instead of Table per Heiarchy. It's much cleaner and crisper looking in the database and you don't get all the information of each type in the heiarchy in one table.
Two: Create a table that specifically holds information that both Students and Teachers share and have that related to both the Student and Teacher table separately. You could call it something like "ContactInformation".
Being a teacher and being a student are roles of people, not types of people.
You should have a table for People, a table TeachCourse to say that a Person is the teacher of a course (which in some cases are multiple teachers), a table AssistCourse to say which persons are attending a class as a student. You might have people that teach a course and assist another course, and that wasn't properly modeled in your first version.
You can also create a ContactInformation or ShippingInformation table for People to specify all their data (Some people may have multiple phones, or emails to).

Cocoa – Core Data object graph

How do I handle the deletion of the following objects? What should my delete rules look like?
Here's what my object graph looks like:
Boss
Boss-Department has a many-to-many-relationship
If a Boss is deleted,
the Departments belonging to that Boss should NOT be deleted (but the
Departments' relationship to this Boss should be deleted)
Department
Department-Employee has a many-to-many relationship
Department-Boss has a many-to-many relationship
If a Department
is deleted, the Employees belonging to that Department should be
deleted IF they don't have a relationship to any other Department
Employee
Employee-Department has a many-to-many relationship
Employees will never be deleted directly (only through the deletion of a department). Oh happy life!
In this situation the Delete rules for your objects should be handled like this
Boss-Department -> Nullify
Department-Employee -> Deny
Department-Boss -> Nullify
Here is what Apple explains the Delete Rules as
Deny: If there is at least one object at the relationship destination,
then the source object cannot be deleted. For example, if you want to
remove a department, you must ensure that all the employees in that
department are first transferred elsewhere (or fired!) otherwise the
department cannot be deleted.
Nullify: Set the inverse relationship for
objects at the destination to null. For example, if you delete a
department, set the department for all the current members to null.
This only makes sense if the department relationship for an employee
is optional, or if you ensure that you set a new department for each
of the employees before the next save operation.
Cascade: Delete the
objects at the destination of the relationship. For example, if you
delete a department, fire all the employees in that department at the
same time.
No Action: Do nothing to the object at the destination of
the relationship. For example, if you delete a department, leave all
the employees as they are, even if they still believe they belong to
that department.
For more information check out the CoreData Programming Guide

refactoring a database and application due to new requirements

My application manages customer's complaints and has already been deployed into production. Each complaint has a code to identify it (for eaxmple "late delivery" ), a "department" type (wich is essentially the department responsible for that kind of complaint) and another "model" code which identifies the route through department's employees this complaint dossier has to follow (first to hr responsible then to hr big boss finally back to customer care). Each dossier has some common info and can have department specific infos, that's why i need deparment code.
For example Customer care get a complaint about "rudeness" of a call center operator, opens a dossier with code ABC and type "HR" (there's could be more HR dossier types). When the customer care has filled all the infos, forward it to hr(a mail is sent to the user configured in the system as HR responsible ). The hr employee fills his own section and send it back to customer care.
Till now each complaint code might have only one department and one model, now requirements have changed and i've two problems:
Some complaints are identified by the same code but might be due to different departments . For example a complaint about employees rudeness could be sent to the department which rules the call centers or to the department which rules logistics
i could solve this simply extending the table primary key to include the department (hoping they'll not decide the same code for the same department can follow different routes), changing application code might be a bit painful but it can be done :
Does extending primary keys to composite keys is a problem in Oracle or have side effects on existing records? the actual primary key is not used as foreign key anywere and all fields are filled.
this is a quite more difficult problem (at least for me): marketing department (the rulers) wants a special dossier.They monitor time departments take to answer complaints and open a new type of dossier if they exceeds the standard time.
For the above example, if hr always needs the 30% more time to complete employees rudeness dossiers, marketing can open an "inquire" dossier about that complaint code directed to hr.
Now, referring to point 1, i could add a new record for each complaint code having the second part of the key being the marketing code and associating it to a new model.This is going to double the rows of the table (which is already quite large). I see it very error prone for inserting new complaint codes.
I know it's very hard to give an opinion without being able to see the schema and the code, but i would appreciate your opinion anyway
"Does extending primary keys to
composite keys is a problem in Oracle
or have side effects on existing
records? the actual primary key is not
used as foreign key anywere and all
fields are filled."
Oracle allows us to have composite primary keys. They are not a problem from a relational perspective.
The only objection to primary composite keys is the usual one, that they make foreign key relationships and joins more cumbersome. You say you currently don't have foreign keys which reference this table. Nevertheless I would suggest you define a synthetic (surrogate) primary key using an index, and enforce the composite key as a unique constraint. Because you may well have foreign keys in the future: your very predicament shows that your current data model is not correct, or at least not complete.
"i could add a new record for each
complaint code having the second part
of the key being the marketing code"
Smart keys are dumb. Add a separate column for a marketing code if necessary. This would be populated if Marketing open their own dossier. I don't see why it needs to be associated with the Complaint Code or form part of any primary key (other than the Marketing Code lookup table).
I admit I don't fully understand your data model or business logic, so the following might be wrong. However what I think you want is a table DOSSIERS which can have two dossier types:
normal dossier identified by DEPT_CODE and COMPLAINT_CODE
Marketing dossier which I presume would be identified by DEPT_CODE, COMPLAINT_CODE and MARKETING_CODE.
Unique constraints permit NULL columns, so MARKETING_CODE can be optional. This is another advantage of using one instead of a composite primary key.
"I see it very error prone for
inserting new complaint codes."
Do you mean creating new complaints? Or new complaint types? Creating new complaints shouldn't be a problem: the process for creating Normal Dossiers will offer a choice of COMPLAINT_CODES where MARKETING_CODE is null, whereas the process for creating Marketing Dossiers will offer a choice of COMPLAINT_CODES where MARKETING_CODE is not null.
If you're talking about adding new complaint types then I suppose the question becomes: does there have to be a separate MARKETING_CODE for each regular COMPLAINT_CODE? I suspect not. In which case, instead of a MARKETING_CODE perhaps you need a CODE_TYPE - values NORMAL or MARKETING.

How do I delete an entity when removing it from an array controller?

I have an entity (e.g. Employee) in a managed object model that is related to two other entities (e.g. Department and Team). Both relationships are one-to-many (i.e. an Employee must have one Department and one Team, Teams and Departments have many Employees). The two may or may not overlap (e.g. a team might be made up of employees from HR, Accounting & I.T. or it might jut consist of several employees from the one department).
Department <-->> Employee <<--> Team
I have two NSArrayControllers providing data for two NSTableViews, a Department table and a Team table. Employees can move between departments and between teams without any problems but I'm not sure how to delete (fire) the employee.
If I send either of the array controllers a remove message the employee is taken out of the team (for example) but left in the department and the object graph is in an inconsistent state. Even if I call the remove action on both controllers the object is not deleted - it is orphaned and just hangs around in limbo.
Originally I had the Department & Team relationships (of the Employee entity) set to a delete rule of Nullify but even changing one or both to cascade doesn't help.
Do I need to override the remove: action on the array controllers to actually delete the employee or am I missing something really obvious?
The NSArrayController has two different behaviors when you're using Core Data. If it is configured to simply fetch objects directly from the managed object context, it will delete the objects when they are removed.
If you're binding the contentSet to another controller, like it sounds like you are in this case, the default behavior is to simply remove the object from the relationship. If you want to delete it, though, there is a "deletes object on remove" binding option, which will produce the result you want.

Resources