Get the default values of table columns in Postgre

2019-01-12 02:36发布

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:

**Editor's note: I fixed the table definition as it has no impact on the question.

CREATE TABLE mytable (
    integer int DEFAULT 2,
    text varchar(64) DEFAULT 'I am default',
    moretext varchar(64) DEFAULT 'I am also default',
    unimportant int 
);

I need a query that would tell me, in some format, that the default for integer is 2, text is 'I am default', and moretext is 'I am also default'. The query result can include any value for any other column that doesn't have a default, i.e., unimportant is unimportant for my purposes and doesn't matter at all.

5条回答
放我归山
2楼-- · 2019-01-12 03:01
you can just type " \d table_name" command , then It will displays some information about the

table, such as the default value of a column.

--create table

skytf=> CREATE TABLE mytable (
skytf(>     a integer DEFAULT 2,
skytf(>     b varchar(64)  DEFAULT 'I am default',
skytf(>     c varchar(64)  DEFAULT 'I am also default'
skytf(> );
CREATE TABLE

--show table information

skytf=> \d mytable
                              Table "skytf.mytable"
 Column |         Type          |                   Modifiers                    
--------+-----------------------+------------------------------------------------
 a      | integer               | default 2
 b      | character varying(64) | default 'I am default'::character varying
 c      | character varying(64) | default 'I am also default'::character varying
查看更多
Deceive 欺骗
3楼-- · 2019-01-12 03:04

Use the information schema:

SELECT column_name, column_default
FROM information_schema.columns
WHERE (table_schema, table_name) = ('public', 'mytable')
ORDER BY ordinal_position;

 column_name │             column_default             
─────────────┼────────────────────────────────────────
 integer     │ 2
 text        │ 'I am default'::character varying
 moretext    │ 'I am also default'::character varying
 unimportant │ 
(4 rows)

Up to the schema naming, this should work in any SQL database system.

查看更多
Emotional °昔
4楼-- · 2019-01-12 03:07

@Zohaib's query is almost but not quite right. There are a couple of issues. I copied it into my answer 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
  • He copied from some blog. That he mentions it is good. But in such a case 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.

  • But 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.

To sum it up:

Copy / pasting from some blog without insight went dangerously wrong!
Try this instead:

SELECT d.adsrc 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';

The LEFT JOIN makes sure you get a result as long as the column exists. If you want to exclude those, make it a JOIN instead. But be prepared to get no rows occasionally.

Be aware that the special cast ::regclass takes the current setting for search_path into account, so even if you do not include the schema in the name (which you should, to be sure!), chances are you get the expected result. Read more about it in the manual.

Including pg_class is redundant, once we have the OID of the table. Skip it and speed up query.

查看更多
孤傲高冷的网名
5楼-- · 2019-01-12 03:18

I liked Erwin's Answer but was having some difficulties:

  1. Sometimes I would get column names "........pg.dropped.30.......", etc. even with the NOT a.attisdropped qualification. It was not consistent, I wound up having to loop through the results and check the column names.
  2. The returned default value sometimes had a cast attached, e.g. 'I am default'::character varying which did not work when they are being stuffed into web form input values. I could not think of a good way to remove the cast suffix without doing something like .replace(/::.*/, '') which is not robust enough. I bet Erwin can figure out some magical way to EVAL() the returned value and use the a.atttypid column to get the right data type.

So I went back to what I was doing before:

BEGIN;
INSERT INTO mytable DEFAULT VALUES RETURNING *;
ROLLBACK;

One thing to note here is that any SERIAL columns will get incremented. It likely does not matter so long as it is unique if it is just a table index. Otherwise it is a deal breaker.

The other thing to watch out for is any TRIGGER AFTER/BEFORE INSERT which will fire even though the INSERT gets rolled back (I think any changes the trigger function makes will get rolled back though.)

查看更多
Luminary・发光体
6楼-- · 2019-01-12 03:23
 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

I found this query for postgresql on one of the blogs. you can try this to check if it works. To get values of all coumns, you can try removing AND pat.attname='your_column_name' from where clause.

查看更多
登录 后发表回答