I have a JSONB column with an array of integers and I’d like to migrate it to a native column of array of integers:
ALTER TABLE MyTable
ALTER COLUMN MyColumn TYPE int[] USING jsonb_array_elements(MyColumn)
However, this does not work:
set-returning functions are not allowed in transform expressions
MyColumn
values look like this: [25,32]
.
2
Answers
I believe its because
jsonb_array_elements
returns a set of rows instead of single value. As mentioned in the comments , I tried a similar approach to create a new column and then updating the new columnFiddle
Output
jsonb_array_elements()
returns a set ofjsonb
, not an array ofinteger
. So twice incorrect.You might use
jsonb_array_elements_text()
instead, cast tointeger
and aggregate that to an array, but that requires a subquery andALTER TABLE
does not allow that in the transform expression.Solution
Create a tiny auxiliary function for the task:
Then you can proceed with
ALTER TABLE
as planned:fiddle
See:
If you don’t want to keep the function around, make it temporary:
See:
Note that
ALTER TABLE
is fundamentally different fromUPDATE
!The former locks the whole table while doing a rewrite, which is much simpler and typically substantially faster. But blocking concurrent access must be avoided in some databases, especially if the table is huge, so it would take a long time. Then, incrementally populating a new column may be the way to go (even if that’s a lot more complex and expensive overall).