Reputation: 43
Part of my database schema involves the entities:
Jobs
Agencies
Agents
and relation JobAgent
The database will be SQL Server 2008
Here is my schema:
My problem is that Jobs.agencyid must always be equal to Agents.agencyid when related through JobAgent. If Jobs.agencyid were to be updated to a new agency, The Agents would then belong to a different Agency than the Job.
What would be the best way to redesign my schema to avoid relying on triggers or application code to ensure this consistency?
Upvotes: 2
Views: 336
Reputation: 5958
The problem is that if a job moves from one agency to another (as you say, if Jobs.agencyid were to be updated...) then the corresponding records in JobAgent become meaningless: those agents can't be attached to a job that's no longer with their agency, so the JobAgent records connecting them to the jobs should therefore be deleted...
One way to enforce this is to add a JobAgent.agencyid field, and make it a foreign key on Jobs.agencyid, with ON UPDATE RESTRICT to force (manual) deletion of the relevant JobAgent records before Jobs.agencyid can be changed.
Edit: the other issue, which I hadn't really considered, is that when you first associate a job to an agent (ie create a new JobAgent record) you need to ensure they both belong to the same agency... for this, I think OMG's solution works best - I'm happy to defer to the better answer.
OMG also raises the question of how to handle updates: you can either
Change the Jobs.agencyid field and delete (by hand) all associated JobAgent records: in this case the old agents no longer work on this job, and you can assign someone from the new agency to work on it.
Change the Jobs.agencyid field and also change all associated JobAgent records (ie all those agents move with the job to the new agency) - but this is very messy, because those agents will also be associated with other jobs that are still with the original agency.
As OMG suggests, make a new Jobs record and mark the old one as defunct (for later deletion).
As above but keep the defunct Jobs record to preserve historical information.
Whether you choose 3 or 4 depends a bit on what your system is for: do you just want to maintain the current state of who-has-which-jobs? or do you need to keep some kind of history, for example if there's billing records attached to the job... that info needs to stay associated with the original agency (but this is all outside the scope of your original question).
Upvotes: 1
Reputation: 332571
You can define more than one foreign key constraint to a column - it just means that the value in JOBAGENT has to satisfy BOTH foreign key constraints to be allowed. But you'll have fun if you ever want to update jobs to a different agency... ;) SQL Server supports composite foreign keys: http://msdn.microsoft.com/en-us/library/ms175464.aspx
You have two choices -
ON UPDATE CASCADE
etc won't handle agency and agent updates without using triggersUpvotes: 1
Reputation: 4335
Does the following scheme answer your question?
Jobs Agents Agencies
^ ^ ^
| | |
\ | /
\ | /
AgentiatedJob
Normally, I have a single-field primary key for every table, because it is easier to match a registry on a table and to refer it on tables below. So following this approach the AgientiatedJob would have at least the fields:
Upvotes: 0
Reputation: 22461
You could use ON UPDATE CASCADE
with the foreign keys. See this Wikipedia Page.
Or maybe, if agencyid
is something that you expect to be mutable, you can have a unique constraint for it and use some other meaningless field for the agency id (say, an auto-increment column).
Upvotes: 0