不是的。这是一个保存重要信息的数据库,具有参照完整性,而不是一个草稿本,因此用户无法仅仅走到它面前并“删除”某些内容。这将违反同一用户维护历史数据(在Reading;Alert;Ack;Action;Download中)的要求。
还有参考表:SensorType; AlertType; ActionType.
使用isObsolete标志存在问题,如果更改位置,则传感器外键将指向已过时的记录,这意味着您必须复制每个传感器记录。随着层次结构的变大,这个问题会呈指数级恶化。
- 好吧,那么现在你明白了,在Sensor表中的LocationId(FK)不会更改;没有大规模复制等等问题吗? 首先根本不存在问题(该愚蠢的书有问题!),其次也不存在成倍恶化的问题。
isObsolete对您的要求不足够。(参见下文)
- 任何真实行的UpdatedDtm(例如Reading等)都可以确定其父行(FK到Sensor的)历史记录的AuditedDtm。
- 完整的关系能力;声明性引用完整性等。
- 保持强标识符的IDEF1X、关系概念...只有一个当前父行(例如位置)。
- 历史中的行是当前行的图像,在更改之前以指定的AuditedDtm显示。当前行(非历史记录)显示最后一次更新日期时间,当行发生更改时。
- AuditedDtm显示了给定密钥的整个系列UpdatedDtms;因此,我已将其用于在时间上“分区”真实密钥。
只需要为每个可更改表提供一个历史记录表。我已经为四个标识表提供了Hiistory表:Location; Sensor; NetworkSlave; and User。
请阅读关于会计意义上的审计以便理解。
数据模型
链接到带有历史记录的Sensor数据模型(第2页包含历史记录表和上下文)。
不熟悉关系建模标准的读者可能会发现 IDEF1X符号有用。
回应评论
(1) 我的首要问题是关于历史数据的引用完整性,我不确定是否存在引用完整性,如果存在,我也不确定它是如何工作的。例如,在SensoryHistory中,可能会添加一个记录,其中UpdatedDtm指示的日期时间早于位置本身存在的时间,如果你明白我的意思的话。不确定这是否真的是一个问题——强制执行可能有些过头。
(您在其他问题中提出了类似的问题。)可能是您遇到的数据库实际上没有实现引用完整性;关系线仅用于文档;引用完整性是“在应用程序代码中实现的”(这意味着没有引用完整性)。
这是一个ISO/IEC/ANSI标准SQL数据库。这允许使用声明性引用完整性。每个关系行都作为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)
REFERENCES Location(LocationId)
...
CREATE TABLE SensorHistory
...
CONSTRAINT UC_PK
PRIMARY KEY (LocationId, SensorNo, UpdatedDtm))
CONSTRAINT Sensor_SensorHistory_fk
FOREIGN KEY (LocationId, SensorNo)
REFERENCES Sensor(LocationId, SensorNo)
...
这些声明的约束由服务器强制实施,而不是通过触发器或应用程序代码。这意味着:
- 不能插入具有不存在于
Location
中的LocationId
的Sensor
- 在
Sensor
中具有行的LocationId
不能被删除
- 不能插入一个在
Sensor
中不存在的LocationId+SensorNo
的记录至SensorHistory
- 在
SensorHistory
中具有LocationId+SensorNo
的行不能被删除
(1.1) 所有列都应该有RULEs和CHECK约束来限制它们的值域。此外,所有的INSERT/UPDATE/DELETE都是通过存储过程编程完成的,因此不会发生意外事故,人们也不会直接访问数据库并运行命令(除了SELECTS)。
通常我避免使用触发器。如果您正在使用存储过程和正常权限,则此问题:
在SensoryHistory中,可能会添加一个记录,其中UpdatedDtm指示的日期时间早于位置本身存在的时间,如果你明白我的意思的话
避免操作。这也适用于在传感器本身之前插入具有更新时间戳的传感器历史记录。但存储过程并不是声明性规则。然而,如果您想要双重确认(我指的是双重确认,因为所有INSERTS都通过存储过程进行,由用户直接命令),那么您必须使用触发器。对我来说,这有点过头了。
(2)如何表示删除?我想我可以向非历史版本的表中添加标志。
还不确定。例如,当删除传感器时,您是否认为它已经被彻底删除...(是的,历史记录会被保留)...然后当将新的传感器添加到位置时,它将具有新的传感器编号...没有传感器被逻辑上替换成新的传感器,无论是否存在时间间隔?
从终端用户的角度来看,他们应该能够自由地添加、编辑和删除传感器,没有任何限制。但是是的,一旦删除就不能恢复。不过,他们以后可以重新添加完全相同参数的传感器。
并且“删除”位置、网络从设备和用户。
好的。然后,在这四个识别表中添加一个IsObsolete
BOOLEAN;现在被认为是足够的。删除现在是软删除。
(2.1) 对于实际上依赖于两个父项的NetworkSensor
和LoggerSensor
,如果其中任何一个父项过时,则它们也将过时。因此,给它们一个具有双重含义、可以从适用的父项中派生的IsObsolete
列是没有意义的。
(2.2) 只是为了明确起见,用户无法从任何事务和历史记录表中删除任何行,对吗?
(3)在更新表时,插入新行到历史表并更新主表的最佳方法是什么?只需要在事务内正常使用SQL语句?
是的。这是ACID属性的经典用法,它是原子性的;它要么完全成功,要么完全失败(在问题得到解决后稍后重试)。
(4)参考书
权威而开创性的文本是C J Date、H Darwen、N A Lorentzos的《时间数据与关系模型》。就像我们这些拥抱RM的人熟悉扩展和在RM的后继产品中所需的内容一样,而不是其他方法。
这本书很糟糕,但是免费的。PDF文档不是真正的PDF(没有搜索和索引功能)。阅读这本书时,微软和甲骨文的开放是有意义的;有一些好东西淹没在很多废话中。内容有许多误导。如果您想要一份适当的评论,请另开一个问题。
(4.1) 除了ValidFrom
之外,还需要ValidTo
。这是该书所犯的严重错误(如本回答开头所指出的),然后又费力地解决。如果你一开始就不犯这个错误,那么你就不需要在第二个地方解决它。据我所知,这将消除触发器。
(4.2) 简单的规则,同时考虑到规范化和时间要求。首先,您需要深入了解(a)时间要求和(b)数据类型、正确用法和限制。始终存储:
瞬间作为DATETIME,例如UpdatedDtm
间隔作为整数,清晰地标识单位在列名中,例如IntervalSec
周期。取决于并联或离散。对于并联,应用(4.1):使用一个DATETIME;下一行的周期开始时间可以从前一行的结束时间中派生。对于离散周期,是的,您需要2个DATETIMEs,例如RentedFrom
和RentedTo
之间有间隔。
(4.3) 他们搞乱了“时间主键”,这使得代码变得复杂(还需要触发器来控制更新异常)。我已经提供了一个干净(经过测试)的时间主键。
(4.4) 他们搞乱了虚拟值、非真实值和“现在”的空值。我不允许在数据库中使用这样的东西。由于我没有存储重复的ValidTo
,所以我没有这个问题,也没有什么需要解决的。
(4.5) 人们会想为什么一本528页的“教科书”在网络上免费提供,而且还是质量很差的PDF格式。
(5) [一个用户]可以完全删除所有LocationHistory行(只留下Location表中的当前版本),即使可能存在一个概念上“属于”之前版本位置的SensorHistory行,如果这有意义的话。
这对我来说没有意义,我们需要消除交流中的障碍。请继续交互,直到解决问题。
在真正的(标准ISO / IEC / ANSI SQL)数据库中,我们不会向用户授予插入/更新/删除权限。我们只授予SELECT和REFERENCES权限(给选定的用户)。所有插入/更新/删除都是在事务中编码的,这意味着存储过程。然后我们向选定的用户授予每个存储过程的EXEC权限(使用角色来减少管理工作)。
因此,没有人可以在没有执行存储过程的情况下从任何表中删除数据。
不要编写用于从任何历史记录表中删除数据的存储过程。这些行不应被删除。在这种情况下,没有权限和不存在的代码是限制条件。
从技术上讲,所有历史记录行都是有效的,不存在需要关注的时间段。最早的LocationHistory行包含了原始Location行在更改之前的图像。最年轻的LocationHistory行是当前Location行的图像。介于两者之间的每个LocationHistory行都是有效的,并适用于期间内的情况。
无需“修剪”或查找一些可以根据未使用的期间删除的LocationHistory行:它们都已使用。(明确地,无需检查任何Location子级与任何LocationHistory行的映射即可证明。)
最重要的是,用户不能从任何历史记录(或事务)表中删除数据。
或者你又有其他意思吗?
请注意我已添加上述(1.1)。
(6) 在DM中更正了一个错误。警报是Reading的表达式,而不是Sensor。
(7) 更正了另一个问题/答案中的业务规则,以反映在此问题中公开的新规则。
(8) 您是否理解并欣赏,由于我们拥有完全符合IDEF1X标准的模型,因此关于标识符: