【问题标题】:Alter column from Integer[] (ARRAY) to Integer in Postgres在 Postgres 中将列从 Integer[] (ARRAY) 更改为 Integer
【发布时间】:2018-11-03 23:58:15
【问题描述】:

如何使用 Postgres type integer[] 数组将整列/所有行数据重铸为 type integer

下面,user_email_id 是type integer[]

\d emails
    Column     |           Type
---------------+------------------------
 id            | integer
 user_id       | integer
 user_email_id | integer[]

SELECT id, user_id, user_email_id FROM emails;

 id | user_id | user_email_id
----+---------+---------------
 65 |       1 | {98,110}
 66 |       1 | {99}

对于 user_email_id={99} 的行,这有效:

ALTER table emails 
ALTER COLUMN user_email_id type integer 
USING user_email_id[1]::INTEGER;

id=66 的预期输出;

\d emails
    Column     |           Type
---------------+------------------------
 id            | integer
 user_id       | integer
 user_email_id | integer

SELECT id, user_id, user_email_id FROM emails where id=66;

 id | user_id | user_email_id
----+---------+---------------
 66 |       1 | 99

但是如果数组{98,110} 中有两个值,该怎么办?在这种情况下,我想我要么必须转换为字符串,要么必须为 id=65; 的记录创建两行?

【问题讨论】:

  • 您希望id=65 行最终成为user_email_id=98user_email_id=110 还是两行?如果是两行,他们会不会有相同的id,生成一个新的id,还是两个新的ids? What about foreign keys that reference that id`?
  • @muistooshort 我认为只有两种解决方案:1)根据每行 user_email_id len() 的大小创建 N 行。 2)转换为字符串,连接所有当前值?如果有两行,它们可以有新的 id。该 id 上没有 FK——I don't think you can create FKs on Postgres Arrays.
  • 对不起,但 (2) 对我来说没有意义,这将倒退到已知的反模式(即“列中的 CSV”)。是的,您不能(AFAIK)从数组中进行 FK,但您当然可以拥有引用包含数组的行(例如示例数据中的 id=65)的 FK。
  • @muistooshort -- 是的,#2 不好。我明白你对 FK 的意思。我将 FK 引用保留在此表之外,因为我打算将 integer[] col 附加到并且我正在测试数组类型

标签: arrays postgresql


【解决方案1】:

我认为您不想尝试将多元素数组混搭成字符串或类似的东西,“列中的 CSV”是一种众所周知的反模式,只会导致痛苦和痛苦。您最好将多元素数组转换为多行。在 cmets 中,您说没有引用此表的 FK,因此您不必担心创建新行。

您可以分步进行。首先使用unnest 和横向连接扩展数组以分隔列:

insert into emails (user_id, user_email_id)
select user_id, array[eid]
from emails,
     unnest(user_email_id) as dt(eid)
where array_length(user_email_id, 1) > 1

这会给你这样的东西:

 id | user_id | user_email_id
----+---------+---------------
 65 |       1 | {98,110}
 66 |       1 | {99}
 X1 |       1 | {98}
 X2 |       1 | {110}

X1X2 行来自65

然后去掉刚刚展开的行:

delete from emails
where array_length(user_email_id, 1) > 1

得到:

 id | user_id | user_email_id
----+---------+---------------
 66 |       1 | {99}
 X1 |       1 | {98}
 X2 |       1 | {110}

最后,使用带有 USING 子句的 ALTER COLUMN 替换数组:

alter table emails
alter column user_email_id
type int using user_email_id[1]

这会给你留下:

 id | user_id | user_email_id
----+---------+---------------
 66 |       1 | 99
 X1 |       1 | 98
 X2 |       1 | 110

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-02
    • 2016-11-19
    • 1970-01-01
    • 1970-01-01
    • 2019-10-13
    • 2019-05-05
    • 2013-02-10
    相关资源
    最近更新 更多