将Integer [](ARRAY)中的列更改为Postgres中的Integer

时间:2018-05-24 17:07:59

标签: arrays postgresql

如何使用其中的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的记录创建两行;?

1 个答案:

答案 0 :(得分:1)

我不认为你想尝试将多元素数组混合成一个字符串或类似的东西,"列中的CSV"是一种众所周知的反模式,只会导致痛苦和痛苦。将多元素数组转换为多行最好。在评论中,您说没有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