Dirk Bergmann

Developer, panographer. Does consultancy work from own company. Lives in Chiang Mai, Thailand.

Twitter

Chiang Mai

Hua Hin

Thailand Hotels

ListVote - List. Vote. Learn.

Partnerseek - Find Partners

PostgreSQL - Add a Column to All Tables in the Database Unless it Exists

To be able to use NHibernate ? and as a general purpose and learning exercise ?  I wanted to write a script that adds a version column of type integer to all tables in the database, unless such column exists (in Rails the schema_migrations table has a version column for example).

In SQL Server we have the ?secret? sproc sp_MSforeachtable for this purpose, but how to bend the stricter syntax of plpgslq to achieve something similar? After a number of hours of trial and error, here's is a script that actually appears to work, at least with PostgreSQL 9.0 and probably earlier versions:

CREATE OR REPLACE FUNCTION add_version_column_to_all_tables()
RETURNS VOID
AS $$
DECLARE
 my_row RECORD;
BEGIN
 FOR my_row IN 
 SELECT table_name
 FROM information_schema.tables
 WHERE table_schema = 'public'
 LOOP
 IF NOT EXISTS
 (
 SELECT attname FROM pg_attribute WHERE attrelid = 
 (SELECT oid FROM pg_class WHERE relname = my_row.table_name )
 AND attname = 'version'
 )
 THEN
 EXECUTE('ALTER TABLE ' || my_row.table_name || ' ADD COLUMN version int NOT NULL DEFAULT 0;');
 END IF;
 END LOOP;
END
$$
LANGUAGE plpgsql;

SELECT add_version_column_to_all_tables();

Im sure this script can be optimized, please post any improvements in the columns.

Hope it helps.

#

dirk: @Sheroz: You have to preplace all inverted commas ? (these are created by Wordpress from single quotes) with normal single quotes. Please let me know if you still have problems.

Shehroz: This script gave following error. ERROR: mismatched parentheses at or near ";" LINE 20: ...able_name || ? ADD COLUMN version int NOT NULL DEFAULT 0;?); Could you please help in tracing it?

Rez: I had error executing this. Problem was in ALTER TABLE statement. It requires name of the table to be in quotes. I changed EXECUTE... line into this EXECUTE('ALTER TABLE "' || result_row.table_name ||'" ADD COLUMN customer_id int;'); and it worked just fine. Thanks again.

ravi: worked. Thanks

Bill: Rez, I had the same issue. It was because the quotes copied from this page were (left quotes) and (right quotes). When I replaced them with (single quotes) it worked fine! WHERE table_schema = 'public' EXECUTE('ALTER TABLE ' || my_row.table_name || ' ADD COLUMN version int NOT NULL DEFAULT 0;');