>(1) Sally deletes an employee record
>(2) Bob deletes that employee's department
I would argue that a good design would actually prevent you from deleting important records like these. i.e. when Bob clicks delete, it just marks the object as deleted and it stops showing up in reports/interfaces. Then maybe you have something clean it up 90 days later or something.
Yes. This is pattern I've seen in both companies I worked for, and it makes so much sense.
Similairly you don't make table ARTICLES with column AMOUNT and KIND. You make table CHANGES with DIFFERENCE and KIND, and only ever add rows to that table (possibly with negative DIFFERENCE).
In the first case, you only know the AMOUNT. You can't undo transactions because you only have 1 object stored, the total amount. If you store DIFFERENCE, then you'll have a table of every transaction and can undo them individually. The cost is having to sum the table whenever you want to know the amount (which is usually worth the flexibility).
Regarding the performance - you can add triggers writing to additional table with a sum, or maintain that table in the code that adds rows, or calculate it each time you want to know the sum.
I would argue that a good design would actually prevent you from deleting important records like these. i.e. when Bob clicks delete, it just marks the object as deleted and it stops showing up in reports/interfaces. Then maybe you have something clean it up 90 days later or something.