3

First, I did read this StackOverflow question, so no need to point me towards it.

I'm working on a similar problem right now. Specifically, I have a database with an Auditing table that is used to store auditing info about other tables within the db. The basic form of this table is:

ID, EntityID, EntityTypeID, ActionTypeID, DateTime

Now, as you can guess, the generic nature of EntityID means that foreign key relationships to and from this table are tricky to manage, especially with you through an ORM system into the mix.

Of course, the grunt-work solution is to do the required queries manually and use the ORM stuff where it works, which I'm fine with.

However, the issue did raise the question in my mind as to whether or not there exists any RDBMS out there that allows for a Foreign Key relationship of the form: Table:ID to be defined.

In other words, in such an RDBMS, the EntityTypeID column might contains values such as

'TableA:1' and 'TableB:somekey'

So...

Is there any RDBMS which does this?

Community
  • 1
  • 1
OOPMan
  • 510
  • 4
  • 8

4 Answers4

5

Audit tables usually cannot have referential integrity constraints on them. An audit table, A, records information about a row of data, R, in some table, T, and contains a series of records for R, each representing R at some a different time. When R is subsequently modified, the information in A does not change, and is not allowed to prevent changes to R. When R is subsequently deleted, the presence of the audit records in A is not allowed to stop that deletion.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • You're right - audit normally means "historical". So FKs can't be created. – Alex Yakunin Jun 26 '09 at 03:31
  • I see the logic of what you're saying with that. However, I would disagree with you with respect to deletion. In most, if not all, of the databases I've worked with there are so many relationships between the various tables within the system that "deleting" a record involves marking it as deleted via a boolean value column rather than actually deleting it. This approach also gels with my attitude that in a RDB data should never truly be removed. – OOPMan Jun 26 '09 at 10:56
  • @OOPMan: I have considerable sympathy with the 'do not delete anything' viewpoint. Temporal databases support that explicitly (or can do). However, I was using the conventional definition of the term DELETE which means the record really does vanish. – Jonathan Leffler Jun 26 '09 at 17:15
1

Btw, obviously, you can implement similar feature with just an RDBMS - by implementing some logic updating the structure of audit tables by the structure of all other tables. You have to:

  1. Extract the structure of all the tables you're going to audit
  2. Find the "hierarchy roots" between them: in fact, you must keep only the tables which primary key isn't marked as foreign key in another table.
  3. Create (or restructure) the audit tables for each of hierarchy roots. Here you need a template with replaceable set of columns containing source table key.

So in general, this isn't an easy task. Even if you have a tool like SQL DOM is capable of extracting the schema and building its parts.

Alex Yakunin
  • 6,330
  • 3
  • 33
  • 52
0

You could look at the option of storing the audit in a separate database, perhaps an Object Oriented database like db4o. This might give you additional flexibility in terms of storage

Rad
  • 8,336
  • 4
  • 46
  • 45
0

I think no RDBMS are supporting similar feature. Relational structure is what you must provide for them first, and they normally don't help you to establish it.

On the other hand, I can describe a nice feature of DataObjects.Net that is quite related to this question: automatic registration of generic instances.

Imagine you have 3 persistent types:

[HierarchyRoot]
public class A : Entity 
{
  [Field, Key]
  long Id { get; set; }

  // ...
}

[HierarchyRoot]
public class B : Entity 
{
  [Field, Key]
  int Id { get; set; }

  // ...
}

// Note: it is a descendant of B
public class C : B
{
  // ...
}

And add one more persistent class:

[HierarchyRoot]
public class AuditData<T> : Entity
  where T: Entity
{
  [Field]
  [Association(OnTargetRemove = OnRemoveAction.None)] // This ensures 
  // FK won't be created
  T Source { get; set; }

  // ...
}

DataObjects.Net will automatically provide persistence for two instances of this type:

  • AuditData(Of A)
  • AuditData(Of B)

But it won't allow you to create AuditData(Of C), since there is AuditData(Of B). So it makes the decision of what to register based on generic type constraints. It's also shown it's easy to avoid creation of foreign key.

Alex Yakunin
  • 6,330
  • 3
  • 33
  • 52