假设我有一张表,用于存储一个人的身高和体重,如下所示:
PersonTable < # ID int, Name varchar(50), Height double, Weight double >
Run Code Online (Sandbox Code Playgroud)
身高以厘米为单位,体重以公斤为单位。
我的问题是关于存储身高和体重的计量单位。
PersonTable < # ID int,
Name varchar(50),
Height double, $ HeightUnit_Id int,
Weight double, $ WeightUnit_Id int >
Units < #ID int, Desription varchar(20) >
Run Code Online (Sandbox Code Playgroud)
HeightUnit_Id 和 WeightUnit_Id 是引用表 Units 中的 Id 的外键。
有没有比我上面提到的明显解决方案更好的解决方案,因为我不喜欢两者(如果做得不好,EAV 会变得混乱,并且添加额外的“单位列”对我来说似乎是浪费空间)?
假设测量类型不会混合(即任何特定行不会混合“公斤”和“英寸”或“磅”和“厘米”),并且还假设该问题的至少部分意图现在与此相关删除相关问题(请注意,除非您有足够的代表点来查看已删除的项目,否则以下链接将不起作用: 处理具有常量部分的复合属性),那么您只需要指出该行使用的度量系统。在此模型中,您将有一个MeasurementSystem
表,该表是外键到任何包含测量值的表。例如(使用 Microsoft SQL Server 语法):
CREATE TABLE dbo.MeasurementSystem
(
MeasurementSystemID TINYINT NOT NULL
CONSTRAINT [PK_MeasurementSystem] PRIMARY KEY
CLUSTERED,
MeasurementSystemName NVARCHAR(50) NOT NULL
);
dbo.Person
(
PersonID INT NOT NULL IDENTITY(1, 1)
CONSTRAINT [PK_Person] PRIMARY KEY
CLUSTERED,
MeasurementSystemID TINYINT NOT NULL
CONSTRAINT [FK_Person_MeasurementSystem]
FOREIGN KEY
REFERENCES dbo.MeasurementSystem (MeasurementSystemID),
Name NVARCHAR(50) NOT NULL
Height FLOAT,
Weight FLOAT,
...
);
INSERT INTO dbo.MeasurementSystem (MeasurementSystemID, MeasurementSystemName)
VALUES (1, N'Metric');
INSERT INTO dbo.MeasurementSystem (MeasurementSystemID, MeasurementSystemName)
VALUES (2, N'United States customary units');
Run Code Online (Sandbox Code Playgroud)
如果您将混合测量系统和/或如果您将允许多个测量单位,即使仅限于一个系统(即允许“毫米”、“厘米”、“米”),则需要有一个额外的层来处理粒度的增加,包括需要Person
表中的每个度量列都有一个 FK 字段。(我可以调整上面的模型以适应这一点,但在这样做之前会等待一些澄清)。
或者,如果各种重量单位和高度单位的组合数量相当有限/有限,那么您可以改为使用每一行来表示可接受的组合之一(例如“cm & kg”、“m & kg”、 “毫米和公斤”/“英寸和磅”,“英尺和磅”)。然后“US”与“Metric”只是查找表每一行的属性。例如:
CREATE TABLE dbo.MeasurementUnit
(
MeasurementUnitID TINYINT NOT NULL
CONSTRAINT [PK_MeasurementUnit] PRIMARY KEY
CLUSTERED,
MeasurementSystem CHAR(1) NOT NULL, -- "M" = Metric, "U" = US
MeasurementSystemName NVARCHAR(50) NOT NULL, -- "Metric" or "US Nonsense"
HeightUnitsName NVARCHAR(20) NOT NULL, -- "Centimeters"
HeightUnitsAlias NVARCHAR(5) NOT NULL, -- "cm"
WeightUnitsName NVARCHAR(20) NOT NULL, -- "Kilograms"
WeightUnitsAlias NVARCHAR(5) NOT NULL -- "kg"
);
dbo.Person
(
PersonID INT NOT NULL IDENTITY(1, 1)
CONSTRAINT [PK_Person] PRIMARY KEY
CLUSTERED,
MeasurementUnitID TINYINT NOT NULL
CONSTRAINT [FK_Person_MeasurementUnit]
FOREIGN KEY
REFERENCES dbo.MeasurementUnit (MeasurementUnitID),
Name NVARCHAR(50) NOT NULL
Height FLOAT,
Weight FLOAT,
...
);
Run Code Online (Sandbox Code Playgroud)
或者,如果需要跨不同测量系统的单位组合,那么我将使用单独的表格 - 每个测量类型一个:“WeightUnits”和“HeightUnits”。我不会在同一个表中混合使用高度和重量单位(即不同行上的“kg”和“cm”)。例如:
CREATE TABLE dbo.WeightUnit
(
WeightUnitID TINYINT NOT NULL
CONSTRAINT [PK_WeightUnit] PRIMARY KEY
CLUSTERED,
MeasurementSystem CHAR(1) NOT NULL, -- "M" = Metric, "U" = US
WeightUnitName NVARCHAR(50) NOT NULL, -- "Kilograms"
WeightUnitAlias NVARCHAR(5) NOT NULL -- "kg"
);
CREATE TABLE dbo.HeightUnit
(
HeightUnitID TINYINT NOT NULL
CONSTRAINT [PK_HeightUnit] PRIMARY KEY
CLUSTERED,
MeasurementSystem CHAR(1) NOT NULL, -- "M" = Metric, "U" = US
HeightUnitName NVARCHAR(50) NOT NULL, -- "Centimeters"
HeightUnitAlias NVARCHAR(5) NOT NULL -- "cm"
);
Run Code Online (Sandbox Code Playgroud)
在此模型中,任何给定表中的每种测量类型都有其自己的测量单位查找表的个人 FK。