【问题标题】:Migrating Oracle DATE columns to TIMESTAMP with timezone将 Oracle DATE 列迁移到带有时区的 TIMESTAMP
【发布时间】:2010-12-12 11:40:06
【问题描述】:

背景: 我有一个正在开发的遗留应用程序,它使用 DATE 类型来存储数据库中的大部分时间。我想尝试更新其中一些表,以便他们可以利用时区,因为这会导致数据库所在不同区域的用户出现问题(请参阅下面的 A)。这是针对 Oracle 10g 的。

问题:

1) 我可以“就地”迁移它吗?那我可以这样转换吗

DATE_COL = type:DATE   =>    DATE_COL = type:TIMESTAMP

...还是我必须使用不同的列名?

请记住,需要保留数据。如果这可以在迁移脚本中轻松完成,那么它将适用于我的目的。

2) 这种类型的转换会向后兼容吗?我们可能有一些我们可能不知道的脚本或报告会出现在此表中。我们可能可以处理它,但我想知道我正在走进什么样的马蜂窝。

3) 我应该注意哪些陷阱?

谢谢,

编辑:
(部分回应加里)

我可以接受多步骤流程。

1) 通过某种转换将数据移动到新的时间戳列(称为 TEMP) 2) 删除旧列(我们称之为 MY_DATE) 3) 使用旧日期列名 (MY_DATE) 创建新的时间戳列 4) 将数据移动到 MY_DATE 列 5) 删除 TEMP 列

A Gary 还想澄清具体的时区问题。我从下面复制了我的答案以使其更具可读性。

基本上,数据将从几个不同的区域访问。我们需要能够根据需要转换到本地时区/从本地时区转换。我们还有使用 sysdate 的触发器使事情变得更加复杂。带有时区的时间戳减轻了很多这种痛苦。

哦,谢谢你到目前为止的回答。

【问题讨论】:

    标签: sql oracle date oracle10g timestamp


    【解决方案1】:

    简单到可以演示

    SQL>  create table x (y date);
    Table created.
    SQL> insert into x select sysdate from dual;
    1 row created.
    SQL> commit;
    Commit complete.
    SQL> alter table x modify y timestamp;
    Table altered.
    SQL> select * from x;
    
    Y
    ---------------------------------------------------------------------------
    03/NOV/09 12:49:03.000000 PM
    SQL> alter table x modify y date;
    Table altered.
    SQL> select * from x;
    Y
    ---------
    03/NOV/09
    SQL> alter table x modify y timestamp with time zone;
    alter table x modify y timestamp with time zone
    ERROR at line 1:
    ORA-01439: column to be modified must be empty to change datatype
    SQL> alter table x modify y timestamp with local time zone;
    Table altered.
    SQL> alter table x modify y date;
    Table altered.
    

    因此,您可以从日期到时间戳(或带有本地时区的时间戳)然后再返回,但不能用于带有时区的时间戳(即保留偏移的地方)。 您必须添加另一列,并复制现有数据(使用适当时区的默认值)。

    “导致与数据库所在不同区域的用户出现问题”。 可能有助于更具体一点。在插入/更改/查询时将日期(或时间戳)从数据库时区转换为用户的时区是否足够,或者您是否真的需要坚持记录是在特定时区的下午 3:00 创建的事实。

    【讨论】:

    • "导致数据库所在不同区域的用户出现问题" 基本上数据将从几个不同的区域访问。我们需要能够根据需要转换到本地时区/从本地时区转换。我们也有使用 sysdate 的触发器使事情进一步复杂化。带有时区的时间戳减轻了很多这种痛苦。
    • 本地时区的时间戳是否可以解决问题。如果是这样,这是最容易实施的解决方案。
    • 附言。当您从另一个日期中减去一个日期时,您会得到一个以天为单位的数字答案。使用时间戳,您将获得一个 INTERVAL 数据类型。这是一个需要寻找的陷阱
    【解决方案2】:

    你可以运行:

    ALTER TABLE your_table MODIFY your_date_column TIMESTAMP WITH TIME ZONE;
    

    但我建议在表中添加一个 TIMESTAMP 列,使用 UPDATE 语句填充,如果您选择删除原始日期列:

    ALTER TABLE your_table ADD date_as_timestamp TIMESTAMP WITH TIME ZONE;
    
    UPDATE your_table
       SET date_as_timestamp = CAST(date_column AS TIMESTAMP WITH TIME ZONE);
    

    转换是向后兼容的 - 您可以根据需要来回切换。

    【讨论】:

    • 我想我想澄清的是,如果我用时间戳替换列(就像我在更新中描述的那样),使用这些字段的报告和查询会在时间戳上阻塞吗? (这将是只读的)我是否可以将时间戳视为日期的子类,或者是否有足够的 oracle 微妙之处来做出非常糟糕的假设?
    • TIMESTAMP 是一种不同的数据类型 - 必须审查报告和查询的影响。这并不是说数据库会“窒息”,而是函数/等在数据类型上可能不灵活,因此必须更新它们以适应。
    • TIMESTAMP 不记录问题所需的时区。您应该使用TIMESTAMP WITH TIME ZONETIMESTAMP WITH LOCAL TIME ZONE。见download.oracle.com/docs/cd/B19306_01/server.102/b14225/…。前者将日期和时区存储在列中,而后者存储归一化为数据库时区的日期,但在用户查询该列时将其转换为用户会话时间。
    • 另一个小提示:如果您添加一个新列并用 CAST(...) 填充它,则当前会话时区将用于转换。但是,如果仅更改列的数据类型,则日期会被解释为 UTC,结果通常会有所不同。
    • 只是想指出第一个 ALTER 语句将失败,要修改的 ORA-01439 列必须为空才能更改数据类型 它适用于日期到时间戳的提升,但不适用于带有时区的日期到时间戳。
    猜你喜欢
    • 2013-12-04
    • 2013-10-09
    • 1970-01-01
    • 2011-02-21
    • 2018-01-13
    • 1970-01-01
    • 1970-01-01
    • 2023-04-01
    • 2022-10-19
    相关资源
    最近更新 更多