问题
Consider designing a database for the traffic department. There is a table for: violations, legalities, and drivers.
In legalities table we have attributes for fine cost, clause number, explanation, reason, etc....
Now if we change the cost & clause number in future, I don't want this to affect the already existing records. But the tables violation and legalities are already in a relationship together, and hence this will change the old records if query for them.
I gave a simple example to illustrate my concern, but I would like to know the concept of solving such a case.
How to do this?
Update 1)
I feel maybe I didn't explain exactly what I want, since some answers are not going in the right direction. Therefore, I will explain: I have entities for:
violation, committee, decision, meeting, and legal terms
Relationship 1 says: committee
holds a meeting
and takes a decision
regarding violation
x.
The other relationship says: the decision
was taken based on the legal terms
.
Now, without going into the details of "legal terms" table, assume it has attributes for fine, legal clauses & references, etc... If one day we change the fine for clause "abc" to be $100 instead of $50, then we retrieve a record of an old violation whose fine was based on the clause "abc", the cost will show $100 although it should show $50.
回答1:
Here's how I would handle this situation:
- First of all I am assuming that your
Violations
table has a date that the violation occurred. If not it should have. - The
Clause
andCost
entities are separate so need to be in separate tables. - The
Violations
table should have a foreign key reference to theClauses
primary key which identifies the individual clause. This ensures that if a clause number changes, you will still reference the correct clause in your violations table. - The
Costs
table should have a foreign key reference to the clause table I.E. each cost record is associated with a clause. - The
Costs
table should have a date column that identifies when the price is valid from. This way a clause can have multiple price records (but only one would ever be considered 'valid' I.E. the one with the latest valid from date). - This means that both the clause number and the price can change independently of each other without affecting the validity of the data in the
Violations
table.
The schema might look something like this:

Then when querying your violations, you simply pull out the latest clause price that was prior to the date the violation occurred.
As an example, assume I have a single clause with the following data:
Id Code Description
---------------------------------
1 101 Speeding
The clause could have the following cost records associated with it:
Id Cost Valid From ClauseId
------------------------------------------------
1 $60 01/01/2013 1
2 $70 01/02/2013 1
3 $80 01/03/2013 1
So all of the above costs are associated with the 'Speeding' clause. If you wanted to know what the current cost was you would select the record from the cost table that is associated with the clause and has the latest valid from date which would give you $80.
Now imagine you had the following violation:
Id Name ClauseId Date Occurred
---------------------------------------------------
1 Benjamin 1 16/02/2013
At the time this violation occurred the cost would have been $70. So in order to select the violation record with the correct price you would want to structure a query that joins the violation, clause and cost tables. You would only select records where the costs valid from date was less than the date the violation occurred.
This would give you the following results:
Name Date Occurred Description cost Valid From
--------------------------------------------------------------------------
Benjamin 16/02/2013 Speeding $60 01/01/2013
Benjamin 16/02/2013 Speeding $70 01/02/2013
You would then simply select the record with the maximum valid from date leaving you with a single row, giving you the correct price of $70 at the time this violation occurred.
回答2:
It's a pretty standard approach that when you want to preserve data for a row in this fashion, for example when you want to preserve the price of a product on an Order or Invoice, you just store the value in the row. For data intended to be unchanging and for which there is a high importance on preserving the value, this is the approach I'd recommend.
回答3:
Taking your example,
In legalities table we have attributes for fine cost, clause number, explanation, reason, etc....
Now if we change the cost & clause number in future, I don't want this to affect the already existing records.
So, let's define the Legalities table.
Legalities
----------
Legalities ID
Explantion
Reason
etc
The Legalities ID is the primary (clustering) key. It's an ascending integer or long, or some other UID.
We define a Clause table. I'm assuming that you change the cost and clause together.
Clause
------
Clause ID
Legalities ID
Date written
Clause
Cost
The Clause ID is the primary (clustering) key. It's an ascending integer or long, or some other UID.
You would define a unique index on (Legalities ID, Date written descending). That way, the first row retrieved would be the most recent clause and cost.
You would define a table like Clause for any columns that you want to keep a history of the changes.
回答4:
The solution is to normalize the tables. Here is a good explanation of the concept:Explain_normalization_with_examples
来源:https://stackoverflow.com/questions/15506542/how-to-keep-data-for-existing-records-unchanged