patternModerate
Storing created/retired dates for a large amount of different entities
Viewed 0 times
createdamountdatesretireddifferentlargeforentitiesstoring
Problem
In the db I'm working on now almost every entity has these 4 columns:
Usually this is used for logging purposes, and for some of the entities the usefulness of knowing when it was retired is arguable (but don't tell my boss). For some other things, (like a truck) it makes more sense because a "retired" vehicle may come back into service.
Anyway, I was wondering if it's a good idea to stick this information into one table since it's repeated all over the place. If it is, anyone have a good name for it..? Simply
CreatedDate
CreatedBy
RetiredDate
RetiredByUsually this is used for logging purposes, and for some of the entities the usefulness of knowing when it was retired is arguable (but don't tell my boss). For some other things, (like a truck) it makes more sense because a "retired" vehicle may come back into service.
Anyway, I was wondering if it's a good idea to stick this information into one table since it's repeated all over the place. If it is, anyone have a good name for it..? Simply
created_retired_dates?Solution
It seems that you are involved in a project that requires the creation of a temporal database. You may as well find related information by searching for the terms auditable databases and database history tables.
I deem this exceptional Stack Overflow answer as the top material with respect to these topics. In such a post, @PerformanceDBA models an auditable relational database for a very interesting business environment, and the instructiveness contained in there encompasses multiple aspects that are pertinent not only to these themes, but also to database design and practice as a whole.
Background
As you know, a database is built to retain information that is relevant to its users, and information, naturally, can change as time passes. In this way, the values contained in a specific database can suffer successive modifications and, as a consequence, go ceasing to be “current”, but these circumstances do not imply that the previous “states” of the values in question become irrelevant after having undergone their corresponding chronological updates.
In this regard, yes, there are cases in which keeping track of the updates that affect an entity over time is paramount, and there are other cases where changes should be expressly forbidden and prevented, hence the retention of entity alterations would not apply. It may seem a cliché, but these points depend on your exact informational requirements, therefore you have to analyze each particular situation thoroughly so that you can define how to proceed. Then, once “audit trail” has been determined valid and necessary, it must be implemented.
Suggested approach
Let us take the
As demonstrated in the aforesaid diagram, apart from depicting the Truck and User entity types, I have included an additional one that represents the History of Truck (denominated, accordingly, TruckHistory).
The only difference between the Truck and the TruckHistory entity types is the PRIMARY KEY of the latter, since it consists of TruckNumber and a complementary property called AuditedDateTime which, of course, indicates the particular point in time when a given Truck occurrence was “audited” (or updated). It is important to note that TruckHistory.TruckNumber is defined as a FOREIGN KEY that points to Truck.TruckNumber, depicting the type of association that takes place between these two entity types.
Taking the present example to the logical level of abstraction, I have derived the following DDL statements from the IDEF1X diagram presented above:
Sample data
Having enabled the logical design previously exposed, say that we are keeping the next two rows in the
+-——————-+-—————————-+-————————-+-——————————-+-——————————-+-———————————————————————-+
| UserId | FirstName | LastName | BirthDate | Gend
I deem this exceptional Stack Overflow answer as the top material with respect to these topics. In such a post, @PerformanceDBA models an auditable relational database for a very interesting business environment, and the instructiveness contained in there encompasses multiple aspects that are pertinent not only to these themes, but also to database design and practice as a whole.
Background
As you know, a database is built to retain information that is relevant to its users, and information, naturally, can change as time passes. In this way, the values contained in a specific database can suffer successive modifications and, as a consequence, go ceasing to be “current”, but these circumstances do not imply that the previous “states” of the values in question become irrelevant after having undergone their corresponding chronological updates.
In this regard, yes, there are cases in which keeping track of the updates that affect an entity over time is paramount, and there are other cases where changes should be expressly forbidden and prevented, hence the retention of entity alterations would not apply. It may seem a cliché, but these points depend on your exact informational requirements, therefore you have to analyze each particular situation thoroughly so that you can define how to proceed. Then, once “audit trail” has been determined valid and necessary, it must be implemented.
Suggested approach
- Illustrative IDEF1X diagram
Let us take the
Truck entity type as a reference since, in accordance with your specifications, it is a good example of an aspect that entails enabling temporal capabilities. In order to illustrate the approach that I am going to propose to construct said capabilities, I have prepared an IDEF1X1 diagram that is shown in Figure 1 (and you can download it as a PDF from Dropbox, as well):As demonstrated in the aforesaid diagram, apart from depicting the Truck and User entity types, I have included an additional one that represents the History of Truck (denominated, accordingly, TruckHistory).
The only difference between the Truck and the TruckHistory entity types is the PRIMARY KEY of the latter, since it consists of TruckNumber and a complementary property called AuditedDateTime which, of course, indicates the particular point in time when a given Truck occurrence was “audited” (or updated). It is important to note that TruckHistory.TruckNumber is defined as a FOREIGN KEY that points to Truck.TruckNumber, depicting the type of association that takes place between these two entity types.
- Resulting expository SQL-DDL logical layout
Taking the present example to the logical level of abstraction, I have derived the following DDL statements from the IDEF1X diagram presented above:
CREATE TABLE UserProfile (
UserId INT NOT NULL,
FirstName CHAR(30) NOT NULL,
LastName CHAR(30) NOT NULL,
BirthDate DATE NOT NULL,
GenderCode CHAR(3) NOT NULL,
Username CHAR(20) NOT NULL,
CreatedDateTime DATETIME NOT NULL,
--
CONSTRAINT UserProfile_PK PRIMARY KEY (UserId),
CONSTRAINT UserProfile_AK1 UNIQUE ( -- Composite ALTERNATE KEY.
FirstName,
LastName,
BirthDate,
GenderCode
),
CONSTRAINT UserProfile_AK2 UNIQUE (Username) -- ALTERNATE KEY.
);
CREATE TABLE Truck ( -- Contains the “current” versions.
TruckNumber INT NOT NULL,
OtherColumn CHAR(10) NOT NULL,
IsRetired BIT NOT NULL,
CreatedUserId INT NOT NULL,
CreatedDateTime DATETIME NOT NULL,
--
CONSTRAINT Truck_PK PRIMARY KEY (TruckNumber),
CONSTRAINT TruckToUserProfile_FK FOREIGN KEY (CreatedUserId)
REFERENCES UserProfile (UserId)
);
CREATE TABLE TruckHistory ( -- Holds the “past” versions.
TruckNumber INT NOT NULL,
AuditedDateTime DATETIME NOT NULL,
OtherColumn CHAR(10) NOT NULL,
IsRetired BIT NOT NULL,
CreatedUserId INT NOT NULL,
CreatedDateTime DATETIME NOT NULL,
--
CONSTRAINT TruckHistory_PK PRIMARY KEY (TruckNumber, AuditedDateTime), -- Composite PRIMARY KEY.
CONSTRAINT TruckHistoryToTruck_FK FOREIGN KEY (TruckNumber)
REFERENCES Truck (TruckNumber),
CONSTRAINT TruckHistoryToUserProfile_FK FOREIGN KEY (CreatedUserId)
REFERENCES UserProfile (UserId),
CONSTRAINT DateSuccession_CK CHECK (AuditedDateTime > CreatedDateTime)
);Sample data
Having enabled the logical design previously exposed, say that we are keeping the next two rows in the
UserProfile table:+-——————-+-—————————-+-————————-+-——————————-+-——————————-+-———————————————————————-+
| UserId | FirstName | LastName | BirthDate | Gend
Code Snippets
CREATE TABLE UserProfile (
UserId INT NOT NULL,
FirstName CHAR(30) NOT NULL,
LastName CHAR(30) NOT NULL,
BirthDate DATE NOT NULL,
GenderCode CHAR(3) NOT NULL,
Username CHAR(20) NOT NULL,
CreatedDateTime DATETIME NOT NULL,
--
CONSTRAINT UserProfile_PK PRIMARY KEY (UserId),
CONSTRAINT UserProfile_AK1 UNIQUE ( -- Composite ALTERNATE KEY.
FirstName,
LastName,
BirthDate,
GenderCode
),
CONSTRAINT UserProfile_AK2 UNIQUE (Username) -- ALTERNATE KEY.
);
CREATE TABLE Truck ( -- Contains the “current” versions.
TruckNumber INT NOT NULL,
OtherColumn CHAR(10) NOT NULL,
IsRetired BIT NOT NULL,
CreatedUserId INT NOT NULL,
CreatedDateTime DATETIME NOT NULL,
--
CONSTRAINT Truck_PK PRIMARY KEY (TruckNumber),
CONSTRAINT TruckToUserProfile_FK FOREIGN KEY (CreatedUserId)
REFERENCES UserProfile (UserId)
);
CREATE TABLE TruckHistory ( -- Holds the “past” versions.
TruckNumber INT NOT NULL,
AuditedDateTime DATETIME NOT NULL,
OtherColumn CHAR(10) NOT NULL,
IsRetired BIT NOT NULL,
CreatedUserId INT NOT NULL,
CreatedDateTime DATETIME NOT NULL,
--
CONSTRAINT TruckHistory_PK PRIMARY KEY (TruckNumber, AuditedDateTime), -- Composite PRIMARY KEY.
CONSTRAINT TruckHistoryToTruck_FK FOREIGN KEY (TruckNumber)
REFERENCES Truck (TruckNumber),
CONSTRAINT TruckHistoryToUserProfile_FK FOREIGN KEY (CreatedUserId)
REFERENCES UserProfile (UserId),
CONSTRAINT DateSuccession_CK CHECK (AuditedDateTime > CreatedDateTime)
);Context
StackExchange Database Administrators Q#107354, answer score: 15
Revisions (0)
No revisions yet.