0

存储有关一行一行元数据的最佳实践是什么?

以银行间金融转账为例。Transfer可能看起来像:

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));

但是现在,当然,人们会希望看到元数据:

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,
    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
)

这些都是明确定义的值,它们都将出现在与转移相关的硬拷贝上。

我们已经对表中的更改进行了审计日志记录,但这不会捕获如下内容:

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

它将捕获进行更改的人的用户名名和机器名;但它无法知道在此人肩上输入其凭据以“授权”接收转移的主管的姓名。

当他们要求跟踪一条信息时,我感到很恼火,我必须在我的数据表中添加更多元数据列。

这是最佳实践吗?

4

2 回答 2

2

这对于财务数据库来说不是很好的做法,因为您允许更新。如果您允许更新,那么记录、审计、加密密钥或您添加的任何内容都无关紧要,因为敌对方可能只是更新它们。

相反,您必须禁止更新;所有更改都必须是插入。所有表都应该有一个索引的顺序 FK 列,并且所有连接都在Max(seq)。这意味着您对最新数据执行所有事务,但对这些表上的每个事务都有永久记录。

编辑:如果您要问的是是否应该将审计列添加到原始表中,这取决于审计列是稀疏的还是可为空的。从你的评论看来,他们是。

在这种情况下,您应该为每个可以为空的审计属性组创建单独的表,并对这些表执行外部连接,与原始数据库的顺序列连接。这意味着您可以随意添加或删除审计表,而不会影响您的数据表。就像是:

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)

Max(seq)如果您需要在事务中重用它,您可以创建保存的视图或存储过程。

于 2011-09-01T16:46:00.387 回答
1

我对 SQL Server 了解不多,但是在 Oracle 场景中遇到这种情况时,我倾向于使用触发器(插入/更新/删除),将完整的行(之前和之后)放入“归档/审计”表并添加他们想要记录的任何“元数据”......这样我的以应用程序为中心的数据模型不会受到关于应用程序/SP等的污染,并且没有应用程序/用户可以访问该敏感的日志记录/审计信息......

于 2011-09-01T16:28:13.137 回答