把退役舰艇的公开参数录进数据库,先想清楚单位

去年帮人整理一批公开的舰艇资料,做一个小型检索库。数据来源是公开年鉴、公开的舰艇手册和维基条目,规模不大,一百多条舰艇,字段也就二十来个:排水量、主尺度、动力、航速、编制人数、服役时间。看上去是个体力活,真做起来坑全在单位上。

第一版表结构我图省事,所有数值字段都用浮点数:

CREATE TABLE ship (
  name TEXT,
  class TEXT,
  displacement REAL,   -- 吨
  length REAL,         -- 米
  beam REAL,           -- 米
  speed REAL,          -- 节
  complement INTEGER,  -- 人
  commissioned TEXT
);

填到第三十条就出问题了。有的资料写「标准排水量 6,000 吨」,有的写「满载 8,200 长吨」,长吨和公吨差 1.6%,一千吨级上就是十几吨,放到对比排序里刚好能让两条船的位次对调。主尺度也有同样的问题:一部分英文资料用英尺,我一开始逐条手算,算到后面开始怀疑人生。

改法是加单位列,不猜、不换算,先原样落库:

ALTER TABLE ship ADD COLUMN displacement_value REAL;
ALTER TABLE ship ADD COLUMN displacement_unit TEXT;  -- 't' / 'lt'
ALTER TABLE ship ADD COLUMN displacement_type TEXT;  -- 'standard' / 'full'

再写一个视图统一换算成公吨、满载口径:

CREATE VIEW ship_norm AS
SELECT name,
  CASE displacement_type
    WHEN 'standard' THEN displacement_value * 1.15
    ELSE displacement_value
  END * CASE displacement_unit WHEN 'lt' THEN 1.01605 ELSE 1 END AS disp_t
FROM ship;

那个 1.15 是标准到满载的粗估系数,只能用来排序,不能当数据引用。这一点我在视图注释里写死了。

为什么值得这么折腾:装备数据一旦进库,后面一定会被拿去做比较和排序,而排序对口径最敏感。单位混着存,错误不会在录入时暴露,会在你给人看结果时暴露。代价是字段变多、查询要过一层视图,写起来啰嗦。

会失效的地方:一是同一级舰不同批次改装后排水量差别不小,单值字段压不住,得拆成按年份的记录;二是编制人数这类整数,公开资料本身就给的是约数,别加约束去校验;三是我一开始用舰名做主键,结果同名舰跨代出现,直接翻车,后来改成「舰名+服役年份」。

顺带说一句工具上的事:英尺转米我最后没手算,用 sqlite 的自定义函数批量刷了一遍,比在表格里拉公式可靠,至少不会漏行。但转换前一定要先备份原值列,我第一次刷的时候把原始英尺数覆盖了,只能回去重抄。

你们录这类公开装备数据时,排水量是统一按满载口径存,还是标准、满载各留一列?我目前两种都试过,还没想好哪种长期更省事。

0
赞同度 100% · 0 条评论 · 11 阅读

0 条评论

支持 Markdown · 回复会实时推送给对方

还没有评论,写下第一条。