I\'m looking for a way to run a query to find the default values of the columns of a table in Postgres. For example, if I made a table with the following query:
System catalogs are the source of truth in Postgres:
SELECT pg_get_expr(d.adbin, d.adrelid) AS default_value
FROM pg_catalog.pg_attribute a
LEFT JOIN pg_catalog.pg_attrdef d ON (a.attrelid, a.attnum) = (d.adrelid, d.adnum)
WHERE NOT a.attisdropped -- no dropped (dead) columns
AND a.attnum > 0 -- no system columns
AND a.attrelid = 'myschema.mytable'::regclass
AND a.attname = 'mycolumn';
LEFT JOIN
guarantees a result as long as the column exists. If there is no default you get NULL
- which happens to be the default default. And almost always correct. But see:
To exclude columns without default, use JOIN
instead and be prepared to get no row occasionally.
The special cast ::regclass
considers the current setting for search_path
. With names that aren't schema-qualified (which you should, to be sure!), you may or may not get the expected result. See rebuttal below. More in the manual. Related:
No need to include pg_class
once we have the OID of the table. Faster without.
@Zohaib's query is almost but not quite right. There are a couple of issues. I copied it here for future reference. Do not use this:
SELECT adsrc as default_value
FROM pg_attrdef pad, pg_atttribute pat, pg_class pc
WHERE pc.relname='your_table_name'
AND pc.oid=pat.attrelid AND pat.attname='your_column_name'
AND pat.attrelid=pad.adrelid AND pat.attnum=pad.adnum
Copied from some blog. Good that it's mentioned, but the source should be added. People reading that blog need to be warned.
Typo in pg_atttribute
- fixed easily.
Doesn't return any rows, if there is no default specified for the requested column. Better make that a LEFT JOIN pg_attrdef ON ..
, so you always get a resulting row if the column exists. It will be NULL, if there is no default, which is actually the correct result because NULL
is the default then.
If you remove attname
from the WHERE clause, you only get values for columns that actually have a default value. Not for others. And you need to add attname
to the SELECT list or you will not know for which column.
The query would also return the default of a column that is already dropped, which is wrong. Read about the details in the manual.
Most importantly: the query can give completely wrong results, as it does not take the schema name into account. There can be any number of table1.col1
in a postgres database: in various schemas. If more than one have a default, you get multiple values. If the column you have in mind does not have a default, but another one in another schema does, you will be fooled and never know it.
Last not least: in recent PostgreSQL releases, the adsrc
column has been removed from pg_attrdef
by commit fe5038236c, as it was redundant, deprecated and unused in PostgreSQL.
To sum it up: C/P from some blog without insight went dangerously wrong.