【问题标题】:Changing time zone value of data更改数据的时区值
【发布时间】:2012-09-22 10:43:15
【问题描述】:

我要在里面导入没有时区信息的数据(不过,我知道我要导入的数据的具体时区),但我需要数据库中的timestamp with time zone格式.一旦我导入它并将时间戳数据类型设置为timestamp with time zone,Postgres 将自动假定表中的数据来自我的时区,并将我的时区分配给它。不幸的是,我要导入的数据不是来自我的时间范围,所以这不起作用。

数据库还包含不同时区的数据。但是,一个表中的时区总是相同的。

现在,我可以在导入数据之前将数据库的时区设置为我要导入的数据的时区(使用SET time zone 命令),并在导入完成后将其更改回我的时区,而且我很确定已经存储的数据不会受到数据库时区更改的影响。但这似乎是一种相当肮脏的方法,以后可能会导致问题。

我想知道是否有一种更优雅的方式来指定导入时区,而不需要在数据本身中包含时区数据?

另外,我还没有找到在导入后编辑时区信息的方法。有没有办法不转换,而只是编辑整个表的时区,假设整个表具有相同的时区偏移量(即,如果在数据输入/导入时分配了错误的偏移量)?

编辑:
我设法在导入时指定了一个时区,整个命令是:

set session time zone 'UTC';
COPY tbl FROM 'c:\Users\Public\Downloads\test.csv' DELIMITERS ',' CSV;
set session time zone 'CET';

然后使用会话时区导入数据。我认为这对同时来自其他连接的数据库上的任何其他查询没有影响?

编辑 2:
后来我发现了如何更改表格的时区:
PostgreSQL update time zone offset

我想在导入后更改表的时区比使用 session 临时更改本地时区更优雅。当然,假设整个表具有相同的时区。

所以现在的代码应该是这样的:

COPY tbl FROM 'c:\Users\Public\Downloads\test.csv' DELIMITERS ',' CSV;
UPDATE tbl SET <tstz_field> = <tstz_field> AT TIME ZONE '<correct_time_zone>';

【问题讨论】:

  • 您的导入效果如何?导入时不能指定时区吗?
  • 感谢提示,我已经更新了我的帖子,但我不确定在执行时设置会话时区对数据库中的其他进程有什么影响?

标签: postgresql datetime timezone timestamp bulk-load


【解决方案1】:

为导入会话设置时区比稍后更新值要高效得多

我的印象是,您将时区视为适用于表格中其他未更改值的设置。但它根本不是那样的。将其视为输入/输出修饰符。实际的timestamp 值(带或不带时区)始终在内部存储为 UTC 时间戳(自'2000-01-01 00:00' 以来的秒数)。更多细节:

第二个示例中的 UPDATE 将表的大小加倍,因为每一行都无效并添加了一个新版本(这就是 UPDATE 在 Postgres 中与 MVCC 一起使用的方式)。除了昂贵的操作之外,VACUUM 以后还需要做更多的工作来清理表膨胀。效率很低。

SET 是会话的本地时区非常安全。这不会以任何方式影响并发操作。顺便说一句,SET SESSION 与普通的SET 相同,因为无论如何SESSION 是默认值。

如果您想绝对确定,可以使用SET LOCAL 将设置限制为当前事务。我引用手册here

SET LOCAL 的效果只持续到当前结束 事务,无论是否已提交。一个特例是SET 跟在后面 通过SET LOCAL 在单个事务中:SET LOCAL 值将是 直到交易结束,但之后(如果 事务已提交)SET 值将生效。

放在一起:

BEGIN;
SET LOCAL timezone = 'UTC';
COPY tabledata FROM 'c:\Users\Public\Downloads\test.csv' DELIMITERS ',' CSV;
COMMIT;

检查:

SHOW timezone;

【讨论】:

  • 正是我需要知道的,很好的解释。丹克·欧文。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-24
  • 1970-01-01
  • 2014-11-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多