Skip to Main Content
  • Questions
  • Please validate the database design of ticket history

Breadcrumb

Question and Answer

Chris Saxon

Thanks for the question, rj.

Asked: December 06, 2019 - 4:53 pm UTC

Last updated: December 10, 2019 - 10:38 am UTC

Version: 11

Viewed 1000+ times

You Asked

Please validate the database design and help is there any better way.
I'm designing database for tracking history of a ticket. the ticket history will store the each change as entry in history table. Please ignore, I have not added created by, created date columns to all tables, that I will.


UI : Ticket form fields looks like below

Ticket Number(field)
Ticket Title(field)
Ticket Description
Ticket Status(drop down value comes from ticket_status[id, name] table)
Ticket Business(drop down values comes from Business[id, name] table)
Ticket Created By(drop down values comes from User[id, name] table)
Ticket Assignee(drop down values comes from User[id, name] table)


Ticket Table structure :

Table : ticket
+--------+-------+-------------+--------+----------+------------+----------+
| number | title | description | status | business | created_by | assignee |
+--------+-------+-------------+--------+----------+------------+----------+
|        |       |             |        |          |            |          |
+--------+-------+-------------+--------+----------+------------+----------+


foreign keys :
ticket_status_id(foreign key reference to ticket_status(ticket_status_id))
ticket_business_id(foreign key reference to business(business_id))
ticket_created_by(foreign key reference to user(user_id))
ticket_assignee(foreign key reference to user(user_id))

Table : ticket_status
+------------------+------------+
| ticket_status_id | name       |
+------------------+------------+
| 1                | Open       |
+------------------+------------+
| 2                | Close      |
+------------------+------------+
| 3                | Inprogress |
+------------------+------------+
| 4                | on hold    |
+------------------+------------+


Table : business
+-------------+---------+
| business_id | name    |
+-------------+---------+
| 1           | Target  |
+-------------+---------+
| 2           | Walmart |
+-------------+---------+
| 3           | TJ Max  |
+-------------+---------+


Table : user
+---------+---------+-------+
| user_id | fname   | lname |
+---------+---------+-------+
| 1       | Aamir   | Mckay |
+---------+---------+-------+
| 2       | Forrest | Bass  |
+---------+---------+-------+
| 3       | Murray  | Tate  |
+---------+---------+-------+



Ticket Hisotry structure : Each field last value and new value will be recorded.

Table : ticket_history_fields
+--------------+-------------------+
|field_id      | name              |
+--------------+-------------------+
| 1            | TICKET_NUMBER     |
+--------------+-------------------+
| 2            | TICKET_TITLE      |
+--------------+-------------------+
| 3            | TICKET_DESC       |
+--------------+-------------------+
| 4            | TICKET_STATUS     |
+--------------+-------------------+
| 5            | TICKET_BUSINESS   |
+--------------+-------------------+
| 6            | TICKET_CREATED_BY |
+--------------+-------------------+
| 7            | TICKET_ASSIGNEE   |
+--------------+-------------------+



Table : ticket_history
+------------+--------+----------+------------+-----------+
| history_id | txn_id | field_id | last_value | new_value |
+------------+--------+----------+------------+-----------+
| 1          | 1      | 2        | server     | AWS       |
+------------+--------+----------+------------+-----------+
| 2          | 1      | 5        | 1          | 2         |
+------------+--------+----------+------------+-----------+
| 3          | 1      | 4        | 1          | 3         |
+------------+--------+----------+------------+-----------+
| 4          | 2      | 7        | 2          | 1         |
+------------+--------+----------+------------+-----------+


Questions :

1. In this design I'm storing last_value and new_value id's or should I store text like below, which one is good and why?
+------------+--------+----------+--------------+-------------+
| history_id | txn_id | field_id | last_value   | new_value   |
+------------+--------+----------+--------------+-------------+
| 1          | 1      | 2        | server       | AWS         |
+------------+--------+----------+--------------+-------------+
| 2          | 1      | 5        | Target       | walmart     |
+------------+--------+----------+--------------+-------------+
| 3          | 1      | 4        | Open         | Inprogress  |
+------------+--------+----------+--------------+-------------+
| 4          | 2      | 7        | Forrest Bass | Aamir Mckay |
+------------+--------+----------+--------------+-------------+



2. Is this is good design or is there any better design for history tracking? How enterprise application do the history tracking like jira.

3. Could you suggest me a book or site for database designing for beginners.


and Chris said...

Before picking a solution, you need to think about WHY you're capturing history. Here are some common reasons:

- Auditing (who changed what, when)
- Error recovery (ooops, I just deleted the wrong row; get it back!)
- Change tracking (viewing the changes, comparing versions, etc.)
- Change management (the customer ordered product version X, current version is Y; ensure you ship them the version X spec)

You can then evaluate your needs against different designs. Here are a few high-level strategies:

Separate history table

Concept:

Every time you update/delete rows in TICKETS, you copy the previous values to TICKETS_HISTORY

create table tickets (
  ticket_number int 
    primary key,
  ...
);

create table tickets_history (
  ticket_number int,
  status_date   date,
  operation     varchar2(1) -- update/delete
  ...
);


Pros: Main tickets table stays relatively small; you can store the history table on slower/cheaper storage if necessary

Cons: Two objects to manage; people may not realize the history table is there => table definitions can get out of sync, ...

Versioning within the table

Concept:

One TICKETS table, with version number/date columns. You disallow updates; instead you "update" a row by inserting a new row with an incremented version number.

create table tickets (
  ticket_number int, ticket_version_number int,
  primary key ( ticket_number, ticket_version_number )
);


Pros: You can have foreign keys from other tables to a given version number; change comparison is easy (select ... where version in ( 1, 4 ))

Cons: If a ticket typically has many changes, this table can grow fast. Can be hard to identify the current version of a ticket

Best for change tracking and management.

Flashback Data Archive

Concept: use the built-in flashback functionality to capture all changes to the table:

alter table tickets flashback archive <archive_name>


Pros: Easy! After the initial setup, the database manages everything for you. And you can use flashback queries to see changes over time.

Cons: The flashback tables are managed by Oracle Database; this makes functionality like "rollback to version X" or "have a foreign key to version Y" are harder/impossible to do.

Best for auditing and error recovery.

So ultimately you need to decide: what is the history data for?

If you're looking for a place to get started with database design, I recommend The Database Programmer blog

http://database-programmer.blogspot.com/2008/09/comprehensive-table-of-contents.html

The section on table design basics gives a good introduction to constraints and normalization.

The posts on table design patterns changed the way I think about tables completely, leading to better databases.

As Ken says:

a code grinder is going to figure it out, while a database programmer is going to spell it out

Rating

  (1 rating)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Questions on - Separate history table

rj, December 09, 2019 - 5:35 pm UTC

I think "Separate history table" is more suitable case for me. But I have question on that.

Ticket table has one to many relationship with 7
tables. do I have to create history tables for those?

example : ticket_watcher, ticket_comment, ticket_workhours...etc these table has one to many relationship.

do I have to create ticket_watcher_history, ticket_comment_history ...etc.

If your answer is yes then it is going to be lot tables for history of each feature in my application. :(
Chris Saxon
December 10, 2019 - 10:38 am UTC

do I have to create history tables for those?

That depends - do you need to store the history for these values and, if so, why?

The fact you're asking leads me to think yes.

You know your requirements better than me. But to be clear:

Separate history tables is my LEAST favourite option of the above.

More to Explore

Design

New to good database design? Check out Chris Saxon's full fundamentals class.