25

The following is a snippet of a table called "containers".

       Column       |            Type             |            Modifiers            
--------------------+-----------------------------+---------------------------------
 id                 | uuid                        | not null
 name               | character varying(255)      | 
 products           | character varying           | default '{}'::character varying

How can I alter the products column to "character varying[]" and the corresponding modifiers to default '{}'::character varying[] ? Essentially, I want to convert a string to a string array. Note the products column has no limit on the number of characters.

alter table "containers" alter "products" type character varying[];

throws the following error

ERROR: column "products" cannot be cast to type character varying[]

klin
  • 112,967
  • 15
  • 204
  • 232
paddle42380
  • 6,921
  • 7
  • 32
  • 40

1 Answers1

36

There is no implicit cast from varchar to varchar[] in Postgres. You must indicate how to perform the conversion of the types. You should do it in USING expression clause (see ALTER TABLE in the documentation). In that case you have to drop and recreate the default value of the column, as it is explained in the documentation:

The USING option of SET DATA TYPE can actually specify any expression involving the old values of the row; that is, it can refer to other columns as well as the one being converted. This allows very general conversions to be done with the SET DATA TYPE syntax. Because of this flexibility, the USING expression is not applied to the column's default value (if any); the result might not be a constant expression as required for a default. This means that when there is no implicit or assignment cast from old to new type, SET DATA TYPE might fail to convert the default even though a USING clause is supplied. In such cases, drop the default with DROP DEFAULT, perform the ALTER TYPE, and then use SET DEFAULT to add a suitable new default.

alter table containers alter products drop default;
alter table containers alter products type text[] using array[products];
alter table containers alter products set default '{}';

The three operations can be done in one statement:

alter table containers 
    alter products drop default,
    alter products type text[] using array[products],
    alter products set default '{}';
klin
  • 112,967
  • 15
  • 204
  • 232
  • 1
    Thanks. Getting this cast error though - ERROR: default for column "products" cannot be cast to type text[] – paddle42380 Feb 08 '13 at 22:32
  • create or replace function string_to_string_array(value character varying) returns character varying[] language sql as $$ select array[$1] $$; and then alter table "containers" alter "products" type character varying[] using string_to_string_array(products); threw the same error as well. – paddle42380 Feb 08 '13 at 22:37
  • How do I change the existing default value as well? – paddle42380 Feb 08 '13 at 22:40
  • Thanks a ton, this worked! Is there a reason you converted the character varying to text? – paddle42380 Feb 08 '13 at 22:50
  • [`text` and `varchar` without length modifier](http://www.postgresql.org/docs/current/interactive/datatype-character.html) are largely interchangeable, but *not* synonyms. I almost exclusively use `text`. – Erwin Brandstetter Feb 09 '13 at 06:27
  • Thanks, you've saved my life! Works great, i've used to convert integer to integer[] – Liuda Dec 01 '16 at 11:42
  • Still helping out the little man - thanks for sharing the 'all in one' bit – TheGeekZn Jun 25 '18 at 13:33