2012-10-01 40 views
8

我必须导入数据,其中没有时区信息(但是,我知道要导入的数据的具体时区),但我需要数据库中的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

我想这是更优雅更改表的时区导入后即可使用会话暂时更改当地时区。假设整个表格当然有相同的时区。

因此,代码会沿着现在的路线的东西:

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

你如何执行你的进口?你不能在导入时指定时区吗? – ertx

+0

感谢您的提示,我已经更新了我的帖子,但我不确定会在执行时在数据库中的其他进程上设置会话时区有什么样的效果? – harbun

回答

11

这是很多更有效地设置时区为您导入会话,而不是更新此值。

我得到的印象是,您认为时区就像适用于表中其他未更改的值的设置。但并不是那样的。把它看作是一个输入/输出修饰符。实际timestamp值(带或不带时区)为始终内部存储为UTC时间戳(自'2000-01-01 00:00'以来的秒数)。很多更多的细节:

在你的第二个例子中的UPDATE加倍表的大小,因为每个单列无效,并增加了新的版本(这是怎么UPDATE作品与MVCC在Postgres的)。除了昂贵的操作,VACUUM将不得不稍后做更多的工作来清理表膨胀。非常无效。

它是完全安全SET为会话的本地时区。这不会以任何方式影响并发操作。 Btw。,SET SESSIONSET相同,因为SESSION是默认设置。

如果你想成为绝对肯定的是,你可以限制设置为当前交易SET LOCAL。我引用的SET LOCAL手动here

的影响仅持续至当前 交易结束时,是否承诺或没有。特殊情况是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; 
+0

**正是**我需要知道的,很好的解释。 Danke Erwin。 :) – harbun

+0

@harbun:Bitteschön。 :) –