更改数据的时区值

har*_*bun 9 postgresql timezone datetime timestamp bulk-load

我必须导入没有时区信息的数据(但是,我知道我要导入的数据的具体时区),但我需要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';
Run Code Online (Sandbox Code Playgroud)

然后使用会话时区导入数据.我假设这对其他连接同时对数据库的任何其他查询没有影响?

编辑2:
我发现如何更改表的时区:
PostgreSQL更新时区偏移量

我想在导入后更改表的时区然后使用会话临时更改本地时区更为优雅.假设整个表当然具有相同的时区.

所以代码现在将是以下内容:

COPY tbl FROM 'c:\Users\Public\Downloads\test.csv' DELIMITERS ',' CSV;
UPDATE tbl SET <tstz_field> = <tstz_field> AT TIME ZONE '<correct_time_zone>';
Run Code Online (Sandbox Code Playgroud)

Erw*_*ter 12

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

我觉得你认为时区就像一个适用于表中其他方面没有变化的值的设置.但它根本不是那样的.将其视为输入/输出修饰符.实际timestamp值(带或不带时区)始终在内部存储为UTC时间戳(自以后的秒数'2000-01-01 00:00').更多细节:

UPDATE为每一个行无效,并增加了新的版本(这是如何在第二个例子中加倍表的大小,UPDATE与作品MVCC在Postgres的).除了昂贵的操作,VACUUM以后还要做更多的工作来清理表膨胀.非常低效.

它是绝对安全SET会话的本地时区.这不会以任何方式影响并发操作.BTW,SET SESSION与plain相同,SET因为SESSION无论如何都是默认值.

如果你想成为绝对肯定的是,你可以限制设置为当前交易SET LOCAL.我在这里引用手册

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;
Run Code Online (Sandbox Code Playgroud)

校验:

SHOW timezone;
Run Code Online (Sandbox Code Playgroud)