开发者

Storing metadata about a row with a database row?

What are the best practices regarding storing metadata about a row with a row?

Take the example of a inter-bank financial transfer. The Transfer might look like:

CREATE TABLE Transfers (
   TransferID int,
   FromTransit varchar(10),
   FromBranch varchar(10),
   FromAccount varchar(50),
   ToTransit varchar(10),
   ToBranch varchar(10),
   ToAccount varchar(50),
   Amount money,
   Status varchar(50));

But now, of course, people will want to see meta-data:

ALTER TABLE Transfers 
ADD
    CreatedDate datetime,
    LastModifiedDate datetime,
    CreatedByUsername varchar(50),
    CreatedByFullname varchar(200),
    CreatedByWorkstation varchar(50),

    VoidedDate datetime NULL,
    VoidedByUsername datetime NULL,
    VoidedByFullname datetime NULL,
    VoidApprovedBySupervisorUsername varchar(50) NULL,
    VoidApprovedBySupervisorFullname varchar(200) NULL,
    VoidApprovedBySupervisorWorkstation varchar(50) NULL,

    SentDate datetime NULL, 
    SentByUsername varchar(50) NULL,
    SentByFullname varchar(50) NULL开发者_如何学Python,
    SentByWorkstation varchar(50) NULL,
    SendApprovedBySupervisorUsername varchar(50) NULL,
    SendApprovedBySupervisorFullname varchar(50) NULL,
    SendApprovedBySupervisorWorkstation varchar(50) NULL,
    SendConfirmationNumber varchar(50) NULL,
    SentToRemoteMachineName varchar(50) NULL,

    ReceivedDate datetime NULL, 
    ReceivedConfirmationNumber varchar(50) NULL,
    ReceivedToRemoteMachineName varchar(50) NULL,
    ReceivedByUsername varchar(50) NULL,
    ReceivedByFullname varchar(50) NULL,
    ReceivedByWorkstation varchar(50) NULL,
    ReceiveApprovedBySupervisorUsername varchar(50) NULL,
    ReceiveApprovedBySupervisorFullname varchar(50) NULL,
    ReceivedApprovedBySupervisorWorkstation varchar(50) NULL,

    ReceivedCheckedBySupervisorUsername varchar(50) NULL,
    ReceivedCheckedBySupervisorFullname varchar(50) NULL,
    ReceivedCheckedBySupervisorWorkstation varchar(50) NULL
)

These are all well-defined values, that will all appear on the hard-copy related to a transfer.

We already have audit logging of changes in tables, but that wouldn't catch something like:

UPDATE Transfers SET Status = 'TransferStatus_Received'
WHERE TransferID = 6744891

It would catch the username, fullname, and machine name of the person who made the change; but it can't know the name of the supervisor who was over the person's shoulder to enter their credentials to "authorize" the transfer to be received.

My aggravation comes when they ask for another piece of information to be tracked, and I have to add more metadata columns to my data table.

Is this best practice?


This is not good practice for financial databases because you allow updates. If you allow updates it does not matter what logging, auditing, crypto keys or whatever you add since a hostile party could just update them.

Instead you must forbid updates; all changes must be inserts. All tables should have an indexed sequential FK column and all joins are on Max(seq). This means you perform all transactions on the latest data but have a permanent record of every transaction on these tables.

Edit: If what you're asking is whether you should add the audit columns to the original table, that depends if the audit columns are sparse or nullable. From your comments, it seems they are.

In that case, you should create separate tables for each nullable group of audit attributes and perform an outer join on those tables, joining with the sequential column of the original database. This means you can add or drop audit tables at will without affecting your data table. Something like:

SELECT t.transferID, t.money, u.Date, u.workstation, s.name, ...
FROM Transfers t
    LEFT OUTER JOIN Users u ON u.seq = t.seq
    LEFT OUTER JOIN Supervisors s ON s.seq = t.seq
WHERE t.seq = (SELECT Max(seq) FROM Transfers WHERE whatever)

You can create a view or stored procedure that saves Max(seq) if you need to reuse it in a transaction.


I don't know much about SQL Server but when confronted with such in an Oracle scenario I tend to employ triggers (insert/update/delete) which take the complete row (before and after) into an "archive/audit" table and add whatever "metadata" they want logged along with it... this way my app-centric data model won't get poluted regarding applications/SPs etc. and no app/user has access to that sensitive logging/auditing information...

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜