【问题标题】:Can you change the data type of a postgres column from TIMESTAMP[] to unix INTEGER[] (and convert data somehow)?您可以将 postgres 列的数据类型从 TIMESTAMP[] 更改为 unix INTEGER[] (并以某种方式转换数据)吗?
【发布时间】:2022-08-18 14:46:05
【问题描述】:

我有一个 postgres 数据库,其中有一个表,该表有一列是 postgres 时间戳(TIMESTAMP [])的数组。由于某些原因,我需要将此列转换为 unix 时间戳 (INTEGER[]) 的整数数组。当我以某种方式更改数据类型时,我想在列中转换一些数据(现有时间戳数组)。

我不太精通sql,曾尝试在谷歌上搜索答案,而我能拼凑的最好的是:

ALTER TABLE crafting_bays 
ALTER COLUMN phases_started_at TYPE integer[]  
USING phases_started_at::integer[];

不过,这给了我 sql 转换错误,说一些关于无法将没有区域的时间戳转换为整数的通用信息。我想我需要以某种方式手动执行此操作,只是不太确定如何解决它。

谢谢

  • 我无法想象为什么有人会丢弃有用的timestamp 并使用可怕的时代。
  • 您知道这很可能会产生新问题吗?如何提取一个月、一周等。如何使用智能索引等保持快速查询。这些整数带来的所有新挑战

标签: sql postgresql


【解决方案1】:

您不能使用ALTER TABLE ... ALTER COLUMN 选项,因为数组没有自动转换选项。相反,你必须以艰难的方式去做。

函数extract(epoch from <column>) 是将时间戳转换为整数所需的函数,但首先您必须将unnest() 转换为数组。甚至在此之前,您必须在表中添加一个新列来保存integer[] 值的数组,然后将它们与UPDATE 绑定在一起,然后删除timestamp[] 的原始列。有点像这样:

ALTER TABLE crafting_bays
    ADD COLUMN tmp integer[];

UPDATE crafting_bays SET tmp = agg
FROM (
    -- Sub-query to convert the timestamps to integer and aggregate back into an array
    SELECT id, array_agg(extract(epoch from ps)) agg
    FROM (
        -- Sub-query to unnest the array into separate rows
        SELECT id, unnest(phases_started) AS ps
        FROM crafting_bays ) x
    GROUP BY id ) y
    WHERE y.id = crafting_bays.id;

ALTER TABLE crafting_bays
    DROP COLUMN phases_started;
ALTER TABLE crafting_bays
    RENAME COLUMN tmp TO phases_started;

VACUUM FULL ANALYZE;

在 PostgreSQL 中,当您执行UPDATE 时,系统实际上会在物理文件中写入一个新行并将原始行标记为已删除。由于您更新每一行,该表将增长到两倍的大小。您可以使用VACUUM 命令回收此空间。

【讨论】:

  • 谢谢!我从来不知道你可以做那种临时设置机制。基于此感谢,我有很多要谷歌的东西!
  • 嗨,frenchy2029,很高兴为您提供帮助。如果这对您有用,那么您应该接受它作为正确答案,以便其他有类似问题的开发人员知道这是一个有效的解决方案。只需单击答案左侧的复选标记即可。
【解决方案2】:

我真的认为这是一个坏主意。

如果您愿意创建一个函数,将正确的时间戳转换为可怕的 epoch 值,则可以使用单个 ALTER TABLE 执行此操作。

create function obfuscate_timestamps(p_input timestamp[]) 
  returns integer[]
as
$$
  select array_agg(extract(epoch from ts)  order by idx)
  from unnest(p_input) with ordinality as x(ts, idx);
$$
language sql
immutable;

然后您可以使用以下方法更改表格:

ALTER TABLE crafting_bays 
   ALTER COLUMN phases_started_at TYPE integer[]  
   USING obfuscate_timestamps(phases_started_at);

请注意,使用integer,您将自己限制为不超过 2038-01-19 的时间戳。你至少应该使用bigint[]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-27
    • 2012-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-13
    相关资源
    最近更新 更多