2011 年 1 月 1 日修订
好的,所以我所在的位置(提供完全可审计的数据库;您的特定要求)与您所在的位置之间存在差距:基于您的问题和评论。我们可能会在评论中解决这个问题。这是一个开始的位置。
为了提供这个要求,根本不需要:触发器;大量复制;完整性受损;等等
这也不是经典的时间要求,因此不需要“周期”功能,但您可以。
ValidFrom和ValidTo 是 Normalization 错误:ValidTo 是容易导出的数据;任意一行的ValidTo重复,在下一行的ValidFrom中;您有更新异常(当您更新一行中的一列时,您还必须更新下一行中的另一列);您必须为“当前”使用虚拟值。
所有这些东西都可以由用户在系统中编辑,并且可以删除。
嗯,不。它是一个保存重要信息的数据库;具有参照完整性,而不是暂存器,因此用户不能只是走到它并“删除”某些东西。它将与维护历史数据的相同用户要求相矛盾(在阅读中;警报;确认;行动;下载)。
不允许级联删除。这些功能是非数据库、MS Access 类型的复选框。对于真实的数据库,RI 约束阻止有孩子的父母被删除。
不能(不应该)更改主键。例如。用户身份; 位置标识;NetworkSlaveCode 永不改变;请记住,它们是经过仔细考虑的Identifiers。PK 的一个特点是它们是稳定的。
您可以添加新用户;您可以更改当前用户的名称;但您不能删除在下载、确认、操作中有条目的用户。
基本上,如果它是可编辑的,那么它必须是历史的(因此不包括读数和警报)。
也不包括:下载;致谢;行动。
以及参考表:SensorType;警报类型;动作类型。
还有新的历史表:它们被插入,但不能被更新或删除。
我发现 isObselete 标志的问题是。假设您更改位置,传感器外键现在将指向一个过时的记录,这意味着您必须复制每个传感器记录。随着层次结构变大,这个问题会呈指数级恶化。
好的,所以现在你明白LocationId
(FK) inSensor
不会改变了吗?没有大量复制等?首先没有问题(在那本愚蠢的书中有!),第二次变得更糟。
IsObsolete
不足以满足您的要求。(参考下文)
UpdatedDtm
任何实际行 (Reading
等) 中的 标识当时有效的父 (FK 到)Sensor
历史行 (its AuditedDtm
)。
完整的关系能力;声明性引用完整性等
维护IDEF1X,强标识符的关系概念......只有一个当前父行(例如位置)
历史记录中的行是当前行的图像,在它被更改之前,在声明的AuditedDtm
. 当前行(非历史记录)显示最后一个 UpdatedDtm,当行更改时。
显示任何给定键AuditedDtm
的整个系列UpdatedDtms
;因此,我用它在时间意义上“划分”了真正的密钥。
所需要的只是每个可更改表的历史表。我为四个识别表提供了历史表:位置;传感器; 网络奴隶;和用户。
请阅读本文以了解会计意义上的 Auditable。
数据模型
链接到具有历史记录的传感器数据模型(第 2 页包含历史记录表和上下文)。
不熟悉关系建模标准的读者可能会发现IDEF1X Notation很有用。
回应评论
(1)我的第一个问题是历史数据的参照完整性,因为我不确定是否存在,如果存在我不确定它是如何工作的。例如,在 SensoryHistory 中,如果您明白我的意思,则可以添加一条记录,该记录具有 UpdatedDtm 指示位置本身存在之前的日期时间。这是否真的是一个我不确定的问题 - 执行这可能是最重要的。
(您在另一个问题中提出了类似的问题。)您所经历的数据库可能实际上没有参照完整性;关系线只是为了记录;RI 是“在应用程序代码中实现的”(这意味着没有 RI)。
这是一个 ISO/IEC/ANSI 标准 SQL 数据库。这允许声明性引用完整性。每个 Relation 行都实现为 PK::FK 引用,即声明的实际约束。例如:
CREATE TABLE Location
...
CONSTRAINT UC_PK
PRIMARY KEY (LocationId)
...
CREATE TABLE Sensor
...
CONSTRAINT UC_PK
PRIMARY KEY (LocationId, SensorNo)
CONSTRAINT Location_Sensor_fk
FOREIGN KEY (LocationId)
REEFERENCES Location(LocationId)
...
CREATE TABLE SensorHistory
...
CONSTRAINT UC_PK
PRIMARY KEY (LocationId, SensorNo, UpdatedDtm))
CONSTRAINT Sensor_SensorHistory_fk
FOREIGN KEY (LocationId, SensorNo)
REEFERENCES Sensor (LocationId, SensorNo)
...
那些声明的约束是由服务器强制执行的;不是通过触发器;不在应用程序代码中。这意味着:
- 不能插入 带有不存在的
Sensor
aLocationId
Location
- 不能删除 包含行的
LocationId
inLocation
Sensor
- 不能插入 带有不存在的
SensorHistory
aLocationId+SensorNo
Sensor
- 不能删除 包含行的in
LocationId+SensorNo
。Sensor
SensorHistory
(1.1)所有列都应该有规则和检查约束来约束它们的值范围。除了所有 INSERT/UPDATE/DELETE 都是程序化的,在存储过程中,因此不会发生意外,人们不会走到数据库并针对它运行命令(SELECTS 除外)。
一般来说,我远离触发器。如果您使用的是存储过程和正常权限,那么:
在 SensoryHistory 中,如果您明白我的意思,可以添加一条记录,该记录具有 UpdatedDtm 指示位置本身存在之前的日期时间
被阻止。因此,在 Sensor 本身之前插入带有 UpdatedDtm 的 SensorHistory 也是如此。但 procs 不是声明性规则。但是,如果您想加倍确定(我的意思是加倍,因为 INSERTS 都是通过 proc,用户直接命令),那么当然,您必须使用触发器。对我来说,这已经超过了顶峰。
(2)如何表示删除?我想我可以在表格的非历史版本中添加一个标志。
还不确定。例如。你是否接受当 aSensor
被删除时,它是最终的......(是的,历史被维护)......然后当一个新Sensor
的被添加到时Location
,它会有一个新的SensorNo
......逻辑上没有Sensor
被替换新的,有或没有时间间隔?
从最终用户的角度来看,他们应该能够通过软件不受限制地随意添加、编辑和删除传感器。但是,是的,一旦删除,它就会被删除并且无法取消删除。尽管使用完全相同的参数,但没有什么可以阻止他们稍后重新添加传感器。
和“删除” Locations, NetworkSlaves
,Users
以及。
行。那么新Sensor
的具有相同参数的,是真正的新的,它有一个新的SensorNo
,并且独立于任何以前的逻辑Sensor
。我们可以IsObsolete
在四个标识表中添加一个 BOOLEAN;现在确定它是足够的。删除现在是软删除。
(2.1) 对于NetworkSensor
和LoggerSensor
,它们实际上依赖于两个父节点:如果它们的父节点中的任何一个已经过时,那么它们就已经过时了。所以给他们一个IsObsolete
列是没有意义的,它具有双重含义,可以从适用的父级派生。
(2.2) 明确一点,用户不能从任何 Transaction 和 History 表中删除任何行,对吗?
(3)更新表时,在历史表中插入新行并更新主表最好用什么方法?可能只是事务中的普通 SQL 语句?
是的。这是事务的经典用法,根据 ACID 属性,它是原子的;它要么在 toto 中成功,要么在 toto 中失败(待问题解决后重试)。
(4) 参考书
权威和开创性的文本是Temporal Data and the Relational Model CJ Date, H Darwen, NA Lorentzos。就像我们这些接受 RM 的人一样,他们熟悉扩展,以及 RM 的继任者需要什么;而不是其他方法。
参考书很可怕,而且免费。PDF 不是 PDF(没有搜索;没有索引)。打开我的 MS 和 Oracle 说明;一些很好的东西藏在很多绒毛中。很多误传。不值得详细回答(如果您想要适当的评论,请打开一个新问题)。
(4.1)ValidTo
除了ValidFrom
。本书所犯的严重错误(如我的答案顶部所述);然后费力地解决。首先不要犯错误,其次你没有什么可解决的。据我了解,这将消除您的触发器。
(4.2) 简单的规则,同时考虑规范化和时间要求。首先,您需要深入了解 (a) 时间要求和 (b) 数据类型、正确用法和限制。始终存储:
(4.3) 他们弄乱了“临时主键”,这使代码复杂化(除了需要触发器来控制更新异常)。我已经交付了一个干净的(经过试验和测试的)临时主键。
(4.4) 他们混淆了虚拟值、非真实值和“现在”的空值。我不允许在数据库中使用这样的东西。由于我没有存储重复的ValidTo
,所以我没有问题,没有什么可解决的。
(4.5) 人们不得不想知道为什么一本 528 页的“教科书”可以在网上免费获得,而且 PDF 格式很差。
(5)例如,我 [an User] 可以安静地删除所有 LocationHistory 行(仅在 Location 表中保留当前版本)——即使可能存在一个 SensorHistory 行在概念上“属于”之前版本的位置,如果这有意义的话。
这对我来说没有意义,我们必须关闭的沟通仍然存在差距。请继续互动,直到它关闭。
(6) 更正了 DM 中的一处错误。AnAlert
是 的表达式Reading
,不是Sensor
。
(7) 更正了其他问题/答案中的业务规则以反映这一点;以及这个问题中暴露的新规则。
(8) 您是否理解/欣赏,因为我们有一个完全符合 IDEF1X 的模型,所以重新标识符: