【问题标题】:Data corruption in PostgreSQL timestamp fieldPostgreSQL 时间戳字段中的数据损坏
【发布时间】:2009-05-14 10:51:42
【问题描述】:

我有一个具有以下架构的 PostgreSQL 表 -

CREATE TABLE test (
  id serial NOT NULL PRIMARY KEY,
  username varchar(100) NOT NULL, -- The user name
  dob timestamp with time zone NOT NULL -- The date of birth
);

然后我用这样的数据将一些数据插入到表中 -

INSERT INTO "test" ("username", "dob") VALUES (E'Scotty', E'2009-05-14 15:44:43');

如果我检查数据库中的数据,我会得到这个 -

mydb=> select username, dob from test where username='Scotty';
 username |            dob            
----------+---------------------------
 Scotty   | 2009-05-14 15:44:43+05:30
(1 row)

在我尝试插入一些日期在 1946 年之前的数据之前,一切都很好——

INSERT INTO "test" ("username", "dob") VALUES (E'James T Kirk', E'1945-01-01 11:30:11');

mydb=> select username, dob from test where username='James T Kirk';
      username |            dob            
-------------- +---------------------------
 James T Kirk  | 1945-01-01 11:30:11+06:30
(1 row)

看看上面的结果。注意时区值是如何从 +05:30 变为 +06:30

当我插入 1942 年之前的任何日期时,它实际上变得更糟 -

INSERT INTO "test" ("username", "dob") VALUES (E'Spock', E'1941-01-01 11:30:11');

mydb=> select username, dob from test where username='Spock';
 username |             dob              
----------+------------------------------
 Spock    | 1941-01-01 11:30:11+05:53:20
(1 row)

现在时区值已完全损坏,无法解析日期。

我将不胜感激。

我的时区是亚洲/加尔各答 (GMT+05:30)。

更新:我尝试通过像这样明确指定 TZ 来输入数据 -

INSERT INTO "test" ("username", "dob") VALUES (E'McCoy', E'1941-01-25 00:20:30+05:30');

即使这样也没有用。

mydb=> select username, dob from test where username='McCoy';
 username |             dob              
----------+------------------------------
 McCoy    | 1941-01-25 00:43:50+05:53:20
(1 row)

【问题讨论】:

    标签: database postgresql rdbms


    【解决方案1】:

    在什么地区?可能 PostgreSQL 假设日期适用于您当前的语言环境,并应用适当的时区和 DST 规则,如果日期和时间是(比如说)UTC,那么这不是正确的做法。

    您真的需要时区功能吗? timestamp without time zone 将表现出更理智的行为,因为它不必实施奇怪的规则。但是,如果您需要时区,那么您肯定想解决这个问题而不是混淆它。

    最好的解决方法是明确指定时区:'04:05:06-08:00' 表示 GMT–08:00,或者'04:05:06z' 表示 GMT/UTC/"Zulu"(因此是“z”)。

    编辑:大部分真正的怪异来自亚洲/加尔各答时区。来自tzdata2009g

    # India
    # Zone  NAME        GMTOFF  RULES   FORMAT  [UNTIL]
    Zone    Asia/Kolkata    5:53:28 -   LMT 1880    # Kolkata
                5:53:20 -   HMT 1941 Oct    # Howrah Mean Time?
                6:30    -   BURT    1942 May 15 # Burma Time
                5:30    -   IST 1942 Sep
                5:30    1:00    IST 1945 Oct 15
                5:30    -   IST
    

    你没有描述你期望的行为,所以很难说你想从这里去哪里。

    【讨论】:

    • 我的时区是亚洲/加尔各答 (GMT+05:30)。你是对的,我宁愿解决这个问题也不愿避免这个问题。
    • 我尝试添加时区(如上所示)。即使那样也没有用。
    • “它不起作用”或“它没有给我预期的答案”?您将需要仔细阅读手册的第 8.5 节,尤其是第 8.5.3 节,以了解如何获得您真正想要的任何行为:postgresql.org/docs/8.3/interactive/datatype-datetime.html
    • 感谢您的信息。这确实是 Django 将数据插入数据库的问题。既然我已经从图片中删除了 Django,那么为什么 PostgreSQL 会以这种方式表现呢? PostgreSQL 不应该解决这个问题吗?
    • 什么问题? PG 手册声称 PG 在时间、日期、时间戳和时区方面符合 SQL 标准,我在这里没有看到相反的证据。
    【解决方案2】:

    这看起来像是夏令时问题。 (据我所知,时区是 UTC+05.30,DST 设置在 3 月/4 月左右,增加一小时)。

    您是否尝试过插入相同的日期并更改年份以排除这种可能性?

    对于最后一个,这很奇怪。我没有设法重现它,但这可能是因为半小时区。改变TZ环境变量是不是也一样?

    【讨论】:

      【解决方案3】:

      我有一个类似但不同的问题。 我们在 WinXP 上安装了 PostgreSQL8.0。

      1. 其中一列是类型 带有时区的时间戳。时间 此列的值随 系统时区的变化。能 我们避免这种情况?
      2. 每次检索后 从餐桌出发,半小时到 每个元组的第一列。

      我无法追踪这个问题的根源。


      rgds 尼丁

      【讨论】:

        猜你喜欢
        • 2011-06-15
        • 2012-08-01
        • 1970-01-01
        • 2015-03-01
        • 2016-12-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多