在数据库中存储时间(hh:mm)的最佳方法

时间:2009-02-11 20:57:04

标签: sql-server database database-design datetime

我想在数据库表中存储时间,但只需要存储小时和分钟。 我知道我可以使用DATETIME并忽略日期的其他组件,但是如果不存储比我实际需要的更多信息,最好的方法是什么?

14 个答案:

答案 0 :(得分:117)

您可以将其存储为午夜过后分钟数的整数:

例如。

0 = 00:00 
60 = 01:00
252 = 04:12

然而,您需要编写一些代码来重新构建时间,但这不应该是棘手的。

答案 1 :(得分:51)

如果您使用的是SQL Server 2008+,请考虑TIME数据类型。 SQLTeam article有更多用法示例。

答案 2 :(得分:9)

只需存储常规日期时间并忽略其他所有内容。为什么要花费额外的时间编写加载int的代码,操作它,并将它转换为日期时间,当你只能加载日期时间时?

答案 3 :(得分:4)

因为如果你在SQL Server 2008上没有提到它,你可以使用time数据类型,否则从午夜开始使用分钟

答案 4 :(得分:2)

我会将它们转换为整数(HH * 3600 + MM * 60),然后以这种方式存储它。存储空间小,仍然可以轻松使用。

答案 5 :(得分:2)

如果您使用的是MySQL,请使用TIME类型的字段类型以及TIME附带的相关功能。

<00> 00:00:00是标准的unix时间格式。

如果您不得不回顾并手动查看表格,整数可能比实际时间戳更令人困惑。

答案 6 :(得分:2)

SQL Server实际上将时间存储为一天的分数。例如,1整天=值为1. 12小时是0.5的值。

如果您想在不使用DATETIME类型的情况下存储时间值,则以十进制形式存储时间将满足该需求,同时还可以简化DATETIME的转换。

例如:

SELECT CAST(0.5 AS DATETIME)
--1900-01-01 12:00:00.000

将值存储为DECIMAL(9,9)将消耗5个字节。但是,如果精度不是最重要的,REAL将只消耗4个字节。在任何一种情况下,聚合计算(即平均时间)都可以很容易地计算数值,但不能计算数据/时间类型。

答案 7 :(得分:1)

尝试smalldatetime。它可能无法满足您的需求,但它可以帮助您满足日期/时间操作的未来需求。

答案 8 :(得分:1)

你确定你只需要时间和分钟吗?如果你想用它做任何有意义的事情(比如两个这样的数据点之间的计算时间跨度),没有关于时区和DST的信息可能会给出不正确的结果。时区可能不适用于您的情况,但DST肯定会。

答案 9 :(得分:1)

而不是在午夜过后的几分钟,我们将其存储为24小时制,作为SMALLINT。

09:12 = 912 14:15 = 1415

当转换回“人类可读形式”时,我们只需在右边插入一个冒号“:”两个字符。如果需要,可以使用零填充左键。以单向方式保存数学,并使用少量字节(与varchar相比),并强制该值为数字(而不是字母数字)

虽然相当愚蠢...... MS SQL中应该有一个TIME数据类型,已经有很多年了吗...

答案 10 :(得分:1)

我认为你要求的是一个将分钟存储为数字的变量。这可以使用不同类型的整数变量来完成:

SELECT 9823754987598 AS MinutesInput

然后,在您的程序中,您只需通过计算即可以您想要的形式查看:

long MinutesInAnHour = 60;

long MinutesInADay = MinutesInAnHour * 24;

long MinutesInAWeek = MinutesInADay * 7;


long MinutesCalc = long.Parse(rdr["MinutesInput"].toString()); //BigInt converts to long. rdr is an SqlDataReader.   


long Weeks = MinutesCalc / MinutesInAWeek;

MinutesCalc -= Weeks * MinutesInAWeek;


long Days = MinutesCalc / MinutesInADay;

MinutesCalc -= Days * MinutesInADay;


long Hours = MinutesCalc / MinutesInAnHour;

MinutesCalc -= Hours * MinutesInAnHour;


long Minutes = MinutesCalc;

如果您要求使用效率,则会出现问题。但是,如果你的时间很短,那么只需使用可空的BigInt来存储你的分钟值。

值为null表示尚未记录时间。

现在,我将以外太空往返的形式解释。

不幸的是,表列只存储单个类型。因此,您需要根据需要为每种类型创建一个新表。

例如:

  • 如果MinutesInput = 0 .. 255 ,请使用 TinyInt (按上述方式转换)。

  • 如果MinutesInput = 256 .. 131071 ,则使用 SmallInt (注意:SmallInt的分钟 值是-32,768。因此,在存储和时,否定并添加32768 如上所述,在转换之前检索值以利用全范围。)

  • 如果MinutesInput = 131072 .. 8589934591 ,请使用 Int (注意:否定并添加 必要时2147483648。

  • 如果MinutesInput = 8589934592 .. 36893488147419103231 ,请使用 BigInt (注意:根据需要添加并取消9223372036854775808。)

  • 如果MinutesInput&gt; 36893488147419103231 然后我会亲自使用 VARCHAR(X)根据需要增加X,因为char是一个字节。我会 我必须在以后重新回答这个问题以完整地描述这个问题 (或者也许是stackoverflowee的同事可以完成这个答案)。

由于每个值无疑都需要一个唯一的密钥,因此只有存储的值的范围是非常小(接近0分钟)和非常高(大于8589934591)之间的良好混合时,数据库的效率才会明显。 。

在存储的值实际上达到大于36893488147419103231的数字之前,您可能还有一个BigInt列来表示您的分钟,因为您不需要在唯一标识符上浪费Int,而另一个int则需要存储分钟值。

答案 11 :(得分:0)

按照克里斯汀的建议,以UTC格式保存时间可以更好。

确保您使用24小时制,因为UTC中没有使用子午线AM或PM。

示例:

  • 4:12 AM - 0412
  • 10:12 AM - 1012
  • 2:28 PM - 1428
  • 11:56 PM - 2356

它仍然更喜欢使用标准的四位数格式。

答案 12 :(得分:0)

ticks存储为long / bigint,目前以毫秒为单位进行测量。通过查看TimeSpan.TicksPerSecond值可以找到更新后的值。

大多数数据库都有一个DateTime类型,它自动将时间存储为幕后的滴答,但对于某些数据库,例如SqlLite,存储刻度可以是存储日期的一种方式。

大多数语言都允许从TicksTimeSpanTicks轻松转换。

示例

在C#中,代码为:

long TimeAsTicks = TimeAsTimeSpan.Ticks;

TimeAsTimeSpan = TimeSpan.FromTicks(TimeAsTicks);

请注意,因为在SqlLite的情况下,它只提供少量不同的类型,它们是; INTREALVARCHAR有必要将刻度数存储为一个字符串或两个INT单元格组合在一起。这是因为INT是32位有符号数,而BIGINT是64位有符号数。

注意

但我个人的偏好是将日期和时间存储为ISO8601字符串。

答案 13 :(得分:-1)

恕我直言,最佳解决方案在某种程度上取决于您如何在数据库的其余部分(以及应用程序的其余部分)存储时间

就我个人而言,我曾与SQLite合作并尝试始终使用unix timestamps来存储绝对时间,所以在处理时间时(就像你要求的那样)我会做Glen Solsberry在他的回答中所写的内容并存储自午夜以来的秒数

当采用这种一般方法时,如果我在任何地方使用相同的标准,那么阅读代码的人(包括我!)就不那么混乱了