我在我的数据模型中存储特定月份(含年份)的值。为简单起见,我们假设我会将这几个月的平均温度存储起来:
| month | degreeCelsius |
+---------+---------------|
| 2010-01 | 5.2 |
| 2010-02 | 6 |
| 2010-03 | 6.8 |
| ... | ... |
现在我想将这些数据保存到PostgreSQL表中,我想知道一个月使用哪种数据类型。在我的Java应用程序中,我使用org.joda.time.YearMonth
类型来表示月份。
基本上我有两个想法:要么我使用date
类型,它也会为" day"这将毫无意义。由于月份是表格的主键,因此在同一个月(但具有不同的日期)不会插入两个值并且我可以可靠地搜索特定年月的平均温度,这一点非常重要。因此,我可以创建一个约束,强制日必须始终是" 1"如果我想要2010年2月的价值,我可以可靠地搜索2010-02-01
。
然而,保持一天的感觉有点尴尬,而其他人在查看数据模型时可能会对当天的部分感到困惑。因此,另一个想法是将该类型拆分为两列:year
和month
。这是否会引入我未能看到的新问题?哪个解决方案更好" /我应该注意哪些缺点?
答案 0 :(得分:2)
我建议约会,因为在sql查询中进行日期算术时可以直接使用它。
请注意,实现您提到的检查约束的一种好方法是执行value=date_trunc('month', value)
。这样您就可以保证没有与该值关联的时间值。 (编辑:实际上没关系,因为postgres有一个不接受时间值的日期数据类型。我已经习惯了oracle,我们会遇到" date"数据类型实际上是时间戳)
答案 1 :(得分:0)
我不喜欢使用日期。在这种情况下,日期违反了最低惊喜原则。
所以我将数月存储为一列或两列。如果你需要做日期算术 - 这在我的经验中是不太可能的 - 你可以得到一个带连接和演员的日期或时间戳。
要注意的两个关键事项是约束和特权。
一栏
在表中存储有效月份,并设置外键引用。
create table months (
cal_month char(7) primary key
);
insert into months
select left(generate_series('2010-01-01'::timestamp,
'2100-12-01'::timestamp,
'1 month')::text, 7);
您希望从几乎所有人撤消对该表的权限。
create table avg_temps (
cal_month char(7) primary key references months (cal_month),
temp_c numeric(3, 1)
);
insert into avg_temps values
('2010-01', 5.2), ('2010-02', 6), ('2010-03', 6.8);
两栏
您可以将基表放在不同的架构中。 (也适用于单列解决方案。)这可以使控制权限变得更加简单。
create schema temperature;
create table temperature.avg_temps (
cal_year integer not null
check (cal_year between 2010 and 2100),
cal_month integer not null
check (cal_month between 1 and 12),
temp_c numeric(3, 1)
);
insert into avg_temps values
(2010, 1, 5.2), (2010, 2, 6), (2010, 3, 6.8);
并使用公共架构中的视图使其看起来整洁。
create view public.avg_temps as
select cal_year || '-' || lpad(cal_month::text, 2, '0') as cal_month, temp_c
from temperature.avg_temps;
我更喜欢自己的单列方法。