swiss_knight
swiss_knight

Reputation: 7831

PostgreSQL rename a column only if it exists

I couldn't find in the PostgreSQL documentation if there is a way to run an: ALTER TABLE tablename RENAME COLUMN IF EXISTS colname TO newcolname; statement.

I would be glad we could, because I'm facing an error that depends on who made and gave me an SQL script, for which in some cases everything is perfectly fine (when the column has the wrong name, name that will actually be changed using a RENAME statement), and in other cases not (when the column already has the right name).

Hence the idea of using an IF EXISTS statement on the column name while trying to rename it. If the column has already the good name (here cust_date_mean), the rename command that must be applied only on the wrong name should be properly skipped and not issuing the following error:

db_1   | [223] ERROR: column "cust_mean" does not exist
db_1   | [223] STATEMENT: ALTER TABLE tablename RENAME COLUMN cust_mean TO cust_date_mean;
db_1   | ERROR:  column "cust_mean" does not exist

(In the meantime I will clarify things with the team so it's not a big deal if such command doesn't exist but I think it could help).

Upvotes: 4

Views: 4839

Answers (1)

Erwin Brandstetter
Erwin Brandstetter

Reputation: 656844

While there is no built-in feature, you can use a DO statement:

DO
$$
DECLARE
   _tbl         regclass := 'public.tbl';      -- not case sensitive unless double-quoted
   _colname     name     := 'cust_mean';       -- exact, case sensitive, no double-quoting
   _new_colname text     := 'cust_date_mean';  -- exact, case sensitive, no double-quoting
BEGIN
   IF EXISTS (SELECT FROM pg_attribute
              WHERE  attrelid = _tbl
              AND    attname  = _colname
              AND    attnum > 0
              AND    NOT attisdropped) THEN
      EXECUTE format('ALTER TABLE %s RENAME COLUMN %I TO %I', _tbl, _colname, _new_colname);
   ELSE
      RAISE NOTICE 'Column % of table % not found!', quote_ident(_colname), _tbl;
   END IF;
END
$$;

Does exactly what you ask for. Enter table and column names in the DECLARE section.
The NOTICE is optional.
For repeated use, I would create a function and pass parameters instead of the variables.

Variables are handled safely (no SQL injection). The table name can optionally be schema-qualified. If it's not, it's resolved according to the current search_path, just like ALTER TABLE would.

Related:

Upvotes: 5

Related Questions