Skip to main content
replaced http://dba.stackexchange.com/ with https://dba.stackexchange.com/
Source Link

You can use a DO statement to run a single dynamic command:

DO
$do$
BEGIN

RAISE NOTICE '%', (
-- EXECUTE (
   SELECT string_agg(format('ALTER TABLE %s ALTER COLUMN %I TYPE text'
                           , a.attrelid::regclass, a.attname), E';\n')
   FROM   pg_attribute a
   JOIN   pg_class     c ON c.oid = a.attrelid
   JOIN   pg_namespace n ON n.oid = c.relnamespace
   WHERE  a.attname = 'description'
   AND    a.atttypid = 'varchar'::regtype
   AND    NOT a.attisdropped                      -- no dropped columns
   AND    a.attnum > 0                            -- no system columns (redundant check)
   AND    format_type(a.atttypid, a.atttypmod) = 'character varying(255)'
   AND    n.nspname NOT LIKE ALL ('{pg_%, information_schema}'::text[])
   );

END
$do$;

Since the command is potentially hazardous I commented the EXECUTE and put a RAISE NOTICE there instead. After confirming the commands are sane, switch the comment characters -- to actually execute the DDL commands.

The manual on format_type().

This changes the type for all columns description varchar(255), except for those in system catalogs, temporary tables (both starting with 'pg_') and the information schema. I build command from the system catalogs. @a_horse demonstrates the other good option@a_horse demonstrates the other good option to use the information schema instead.

In your particular case, there can only be one column per table. If there can be multiple, it would be substantially cheaper to execute all type changes in a single ALTER TABLE statement per table. Commands of the form:

ALTER TABLE foo
    ALTER COLUMN col1 TYPE text
  , ALTER COLUMN col2 TYPE text
  , ALTER COLUMN col3 TYPE text;

More details in this related answer:
Dynamic UPDATE fails due to unwanted parenthesis around string in plpgsqlDynamic UPDATE fails due to unwanted parenthesis around string in plpgsql

You can use a DO statement to run a single dynamic command:

DO
$do$
BEGIN

RAISE NOTICE '%', (
-- EXECUTE (
   SELECT string_agg(format('ALTER TABLE %s ALTER COLUMN %I TYPE text'
                           , a.attrelid::regclass, a.attname), E';\n')
   FROM   pg_attribute a
   JOIN   pg_class     c ON c.oid = a.attrelid
   JOIN   pg_namespace n ON n.oid = c.relnamespace
   WHERE  a.attname = 'description'
   AND    a.atttypid = 'varchar'::regtype
   AND    NOT a.attisdropped                      -- no dropped columns
   AND    a.attnum > 0                            -- no system columns (redundant check)
   AND    format_type(a.atttypid, a.atttypmod) = 'character varying(255)'
   AND    n.nspname NOT LIKE ALL ('{pg_%, information_schema}'::text[])
   );

END
$do$;

Since the command is potentially hazardous I commented the EXECUTE and put a RAISE NOTICE there instead. After confirming the commands are sane, switch the comment characters -- to actually execute the DDL commands.

The manual on format_type().

This changes the type for all columns description varchar(255), except for those in system catalogs, temporary tables (both starting with 'pg_') and the information schema. I build command from the system catalogs. @a_horse demonstrates the other good option to use the information schema instead.

In your particular case, there can only be one column per table. If there can be multiple, it would be substantially cheaper to execute all type changes in a single ALTER TABLE statement per table. Commands of the form:

ALTER TABLE foo
    ALTER COLUMN col1 TYPE text
  , ALTER COLUMN col2 TYPE text
  , ALTER COLUMN col3 TYPE text;

More details in this related answer:
Dynamic UPDATE fails due to unwanted parenthesis around string in plpgsql

You can use a DO statement to run a single dynamic command:

DO
$do$
BEGIN

RAISE NOTICE '%', (
-- EXECUTE (
   SELECT string_agg(format('ALTER TABLE %s ALTER COLUMN %I TYPE text'
                           , a.attrelid::regclass, a.attname), E';\n')
   FROM   pg_attribute a
   JOIN   pg_class     c ON c.oid = a.attrelid
   JOIN   pg_namespace n ON n.oid = c.relnamespace
   WHERE  a.attname = 'description'
   AND    a.atttypid = 'varchar'::regtype
   AND    NOT a.attisdropped                      -- no dropped columns
   AND    a.attnum > 0                            -- no system columns (redundant check)
   AND    format_type(a.atttypid, a.atttypmod) = 'character varying(255)'
   AND    n.nspname NOT LIKE ALL ('{pg_%, information_schema}'::text[])
   );

END
$do$;

Since the command is potentially hazardous I commented the EXECUTE and put a RAISE NOTICE there instead. After confirming the commands are sane, switch the comment characters -- to actually execute the DDL commands.

The manual on format_type().

This changes the type for all columns description varchar(255), except for those in system catalogs, temporary tables (both starting with 'pg_') and the information schema. I build command from the system catalogs. @a_horse demonstrates the other good option to use the information schema instead.

In your particular case, there can only be one column per table. If there can be multiple, it would be substantially cheaper to execute all type changes in a single ALTER TABLE statement per table. Commands of the form:

ALTER TABLE foo
    ALTER COLUMN col1 TYPE text
  , ALTER COLUMN col2 TYPE text
  , ALTER COLUMN col3 TYPE text;

More details in this related answer:
Dynamic UPDATE fails due to unwanted parenthesis around string in plpgsql

added 916 characters in body
Source Link
Erwin Brandstetter
  • 182.1k
  • 28
  • 457
  • 620

You can use a DO statement to run a single dynamic command:

DO
$do$
BEGIN

RAISE NOTICE '%', (
-- EXECUTE (
   SELECT string_agg(format('ALTER TABLE %s ALTER COLUMN %I TYPE text'
                           , a.attrelid::regclass, a.attname), E';\n')
   FROM   pg_attribute a
   JOIN   pg_class     c ON c.oid = a.attrelid
   JOIN   pg_namespace n ON n.oid = c.relnamespace
   WHERE  a.attname = 'description'
   AND    a.atttypid = 'varchar'::regtype
   AND    NOT a.attisdropped                      -- no dropped columns
   AND    a.attnum > 0                            -- no system columns (redundant check)
   AND    format_type(a.atttypid, a.atttypmod) = 'character varying(255)'
   AND    n.nspname NOT LIKE ALL ('{pg_%, information_schema}'::text[])
   ); 

END
$do$;

Since the command is potentially hazardous I commented the EXECUTE and put a RAISE NOTICE there instead. After confirming the commands are sane, switch the comment characters -- to actually execute the DDL commands.

The manual on format_type().

This changes the type for allall columns description varchar(255), except for those in system catalogs, temporary tables (both starting with 'pg_') and the information schema. I build command from the system catalogs. @a_horse demonstrates the other good option to use the information schema instead.

In your particular case, there can only be one column per table. If there can be multiple, it would be substantially cheaper to execute all type changes in a single ALTER TABLE statement per table. Commands of the form:

ALTER TABLE foo
    ALTER COLUMN col1 TYPE text
  , ALTER COLUMN col2 TYPE text
  , ALTER COLUMN col3 TYPE text;

More details in this related answer:
Dynamic UPDATE fails due to unwanted parenthesis around string in plpgsql

You can use a DO statement to run a single dynamic command:

DO
$do$
BEGIN

RAISE NOTICE '%', (
-- EXECUTE (
   SELECT string_agg(format('ALTER TABLE %s ALTER COLUMN %I TYPE text'
                           , a.attrelid::regclass, a.attname), E';\n')
   FROM   pg_attribute a
   JOIN   pg_class     c ON c.oid = a.attrelid
   JOIN   pg_namespace n ON n.oid = c.relnamespace
   WHERE  a.attname = 'description'
   AND    a.atttypid = 'varchar'::regtype
   AND    format_type(a.atttypid, a.atttypmod) = 'character varying(255)'
   AND    n.nspname NOT LIKE ALL ('{pg_%, information_schema}'::text[])
   );
END
$do$;

Since the command is potentially hazardous I commented the EXECUTE and put a RAISE NOTICE there instead. After confirming the commands are sane, switch the comment to actually execute the DDL commands.

This changes the type for all columns description varchar(255), except for those in system catalogs, temporary tables (both starting with 'pg_' and the information schema.

You can use a DO statement to run a single dynamic command:

DO
$do$
BEGIN

RAISE NOTICE '%', (
-- EXECUTE (
   SELECT string_agg(format('ALTER TABLE %s ALTER COLUMN %I TYPE text'
                           , a.attrelid::regclass, a.attname), E';\n')
   FROM   pg_attribute a
   JOIN   pg_class     c ON c.oid = a.attrelid
   JOIN   pg_namespace n ON n.oid = c.relnamespace
   WHERE  a.attname = 'description'
   AND    a.atttypid = 'varchar'::regtype
   AND    NOT a.attisdropped                      -- no dropped columns
   AND    a.attnum > 0                            -- no system columns (redundant check)
   AND    format_type(a.atttypid, a.atttypmod) = 'character varying(255)'
   AND    n.nspname NOT LIKE ALL ('{pg_%, information_schema}'::text[])
   ); 

END
$do$;

Since the command is potentially hazardous I commented the EXECUTE and put a RAISE NOTICE there instead. After confirming the commands are sane, switch the comment characters -- to actually execute the DDL commands.

The manual on format_type().

This changes the type for all columns description varchar(255), except for those in system catalogs, temporary tables (both starting with 'pg_') and the information schema. I build command from the system catalogs. @a_horse demonstrates the other good option to use the information schema instead.

In your particular case, there can only be one column per table. If there can be multiple, it would be substantially cheaper to execute all type changes in a single ALTER TABLE statement per table. Commands of the form:

ALTER TABLE foo
    ALTER COLUMN col1 TYPE text
  , ALTER COLUMN col2 TYPE text
  , ALTER COLUMN col3 TYPE text;

More details in this related answer:
Dynamic UPDATE fails due to unwanted parenthesis around string in plpgsql

Source Link
Erwin Brandstetter
  • 182.1k
  • 28
  • 457
  • 620

You can use a DO statement to run a single dynamic command:

DO
$do$
BEGIN

RAISE NOTICE '%', (
-- EXECUTE (
   SELECT string_agg(format('ALTER TABLE %s ALTER COLUMN %I TYPE text'
                           , a.attrelid::regclass, a.attname), E';\n')
   FROM   pg_attribute a
   JOIN   pg_class     c ON c.oid = a.attrelid
   JOIN   pg_namespace n ON n.oid = c.relnamespace
   WHERE  a.attname = 'description'
   AND    a.atttypid = 'varchar'::regtype
   AND    format_type(a.atttypid, a.atttypmod) = 'character varying(255)'
   AND    n.nspname NOT LIKE ALL ('{pg_%, information_schema}'::text[])
   );
END
$do$;

Since the command is potentially hazardous I commented the EXECUTE and put a RAISE NOTICE there instead. After confirming the commands are sane, switch the comment to actually execute the DDL commands.

This changes the type for all columns description varchar(255), except for those in system catalogs, temporary tables (both starting with 'pg_' and the information schema.