I am having a hard time getting a relational model out of my project's requirements.
The general context is about devices posting sensor data.
In the table representations, the PKs of each table are above the dashed line and I also include some sample data. Any irrelevant column is omitted.
- There are various types of sensors discriminated by the kind of data they read. We have 'Measure' sensors measuring a quantity as a NUMERIC value (e.x. temperature) and sensors reading a state/switch change as a BIT value(e.x. opening-closing of a door).
[SensorType]
######################## | SensorTypeCode | ReadingTypeCode |
# SensorTypeCode # ------------------------------------
# -------------------- # | Temperature | Measure |
# ReadingTypeCode # | Humidity | Measure |
######################## | Door | Switch |
- There are various types of devices in respect to the types of sensors they contain. Only one of each type of sensor can be contained in a device. A device type is immutable regarding the sensor types it contains.
[DeviceType]
######################## | DeviceTypeCode |
# DeviceTypeCode # ------------------
# -------------------- # | D_TYPE_1 |
######################## | D_TYPE_2 |
[DeviceTypeSensorType]
######################## | DeviceTypeCode | SensorTypeCode |
# DeviceTypeCode # -----------------------------------
# SensorTypeCode # | D_TYPE_1 | Temperature |
# ---------------------# | D_TYPE_1 | Humidity |
######################## | D_TYPE_2 | Temperature |
| D_TYPE_2 | Door |
- A device has a unique identifier and a type. The type of a device can change, meaning that sensors can be added or removed.
[Device]
######################## | DeviceMacAddress | DeviceTypeCode |
# DeviceMacAddress # -------------------------------------
# ---------------------# | 00:00:00:00:00:00 | D_TYPE_1 |
# DeviceTypeCode # | FF:FF:FF:FF:FF:FF | D_TYPE_2 |
########################
- The devices post readings that contain some common fields, independently of the device type and sensor types contained in the device.
[Reading]
########################
# DeviceMacAddress #
# ReadingDtm #
# ---------------------#
# BatteryLevel #
# ... #
########################
Additionally, a device reading contains data related to the all of the device's sensors. That would be two child tables of Reading
, ReadingMeasure
and ReadingSwitch
, storing sensor data discriminated by the ReadingTypeCode
discriminator.
Here is where I start having some trouble finding a solution. As I said before, the device type can change, but a change should not affect any past readings that should still be available.
1st approach
Create a device history table storing any previous device types and add an UpdatedDtm
field in Devices
, following the modelling process described here.
[DeviceHistory]
########################
# DeviceMacAddress #
# AuditedDtm #
# ---------------------#
# DeviceTypeCode #
# UpdatedDtm #
########################
Structuring the Reading{Type}
tables as:
[ReadingMeasure] [ReadingSwitch]
######################## ########################
# DeviceMacAddress # # DeviceMacAddress #
# ReadingDtm # # ReadingDtm #
# DeviceTypeCode # # DeviceTypeCode #
# SensorTypeCode # # SensorTypeCode #
# ---------------------# # ---------------------#
# Value (NUMERIC) # # Value (BIT) #
######################## ########################
with
- (
DeviceMacAddress
,ReadingDtm
) FK referencingReading
- (
DeviceType
,SensorType
) FK referencingDeviceTypeSensorType
That way I can just update Device.DeviceTypeCode
and the (DeviceType
,SensorType
) FK will still have a valid reference to an immutable row in DeviceTypeSensorType
. Any new readings will be inserted taking into account the new device type.
It seems to me that I lose a lot of referential integrity that way and I would like a better solution. All database operations will be done through stored procedures implementing the necessary checks anyway, so maybe this approach is acceptable ?
2nd approach
I addition to the tables of the previous approach, also create a Sensor
table and two exclusive subtypes of Sensor
, SensorMeasure
and SensorSwitch
[Sensor]
########################
# DeviceMacAddress #
# DeviceTypeCode #
# SensorTypeCode #
# ---------------------#
# IsObsolete #
########################
| DeviceMacAddress | DeviceTypeCode | SensorTypeCode | IsObsolete |
---------------------------------------------------------------------
| 00:00:00:00:00:00 | D_TYPE_1 | Temperature | 0 |
| 00:00:00:00:00:00 | D_TYPE_1 | Humidity | 0 |
| FF:FF:FF:FF:FF:FF | D_TYPE_1 | Temperature | 0 |
| FF:FF:FF:FF:FF:FF | D_TYPE_1 | Door | 0 |
[SensorMeasure] [SensorSwitch]
######################## ########################
# DeviceMacAddress # # DeviceMacAddress #
# DeviceTypeCode # # DeviceTypeCode #
# SensorTypeCode # # SensorTypeCode #
# ---------------------# # ---------------------#
######################## ########################
In this case:
ReadingMeasure
andReadingSwitch
will have an FK (DeviceMacAddress
,DeviceTypeCode
,SensorTypeCode
) referencingSensorMeasure
andSensorSwitch
respectively.Sensor
will have an FK (DeviceTypeCode
,SensorTypeCode
) referencingDeviceTypeSensorType
.- An insert to
Device
leads to the appropriateSensor
inserts, depending on the device type. - On device type change, i will mark any sensor removal or re-installation setting
Sensor.IsObsolete
I think this approach provides more integrity but requires many redundant relations that seem unavoidable. All the data in the three new tables is already accessible through Device.DeviceTypeCode
.
Any thoughts?