Does PostgreSQL support generated columns? Also know as virtual columns. I am not talking about IDENTITY columns.

I can’t find any information on this remarkable feature but I know that it is available on SQL Server, and in the latest versions of MariaDB & MySQL.

The feature is mentioned in the SQL:2003 standard, and there was some discussion on the PostgreSQL forums around 2006, but I can’t find anything substantial on the matter.

There is some discussion on SO, but it is quite old now, so it may well be out of date.


Not sure if this is what you want, but attribute notation row.full_name and function notation full_name(row) are equivalent in postgresql.

That means you take a table

  first_name text,
  last_name text

and a function:

CREATE FUNCTION full_name(people) RETURNS text AS $$
  SELECT $1.first_name || ' ' || $1.last_name;

and call it like this:

select full_name from people

Is that what you need?

To speed up things you can create an expression index:

CREATE INDEX people_full_name_idx ON people
USING GIN (to_tsvector('english', full_name(people)));

Or store everything in a materialised view.

Example taken from here: http://bernardoamc.github.io/sql/2015/05/11/postgres-virtual-columns/

  • 2
    This is the correct answer. See, for example, how Postgrest refers to this behavior as "computed columns". – fiatjaf Nov 8 '17 at 17:03
  • Typo, I think - the select should be of select people.full_name from people or select full_name(people) from people? – Barguast Dec 21 '17 at 17:16
  • No it works like that. The prefix in "select people.full_name from people" can be left out like in regular SQL. – Fabian Zeindl Dec 25 '17 at 22:06
  • I missed this answer, coming, as it were, long after I’d given up. Thanks for the suggestion. – Manngo May 12 '18 at 7:55
  • 1
    Could you change the accepted answer then? – Fabian Zeindl May 26 '18 at 13:21

No, this is currently (as of Postgres 9.6) not supported.

The only workaround is to use a trigger or a view if it's a simple calculation that you do not need to index.

  • Rats. I suppose I could go for a materialised view if I need the performance. I have added a request for the feature, as it’s already available in the competition. – Manngo Mar 10 '17 at 8:48
  • 1
    No need for a MVIEW. A column with a trigger will also let you index the column's content – a_horse_with_no_name Mar 10 '17 at 8:50
  • I have a philosophical issue with storing additional real columns which are basically a repeat of the other data. It de-normalises the table. – Manngo Mar 13 '17 at 8:39
  • 4
    Well, a computed column is exactly that: storing de-normalized data. How the computed column's value is generated doesn't matter. I don't see a conceptual difference between a "real" computed column and one that is generated through a trigger – a_horse_with_no_name Mar 13 '17 at 8:56
  • Another workaround (for some cases) is to index an expression. – ypercubeᵀᴹ Jul 18 '17 at 11:51

Depending on your use-case, you could achieve this sort of behavior by declaring a new column and populating it with a trigger on insert/update.

I would use the above answers if possible to avoid duplicating data that could be derived form what you already have, but it does do the trick and could be useful for computationally intensive derived fields that you want to compute once and save.

I considered this approach to deal with an issue where I sometimes only had 15 digits of an 18-digit key (the last 3 digits are just a checksum) but wanted to be able to enforce a foreign-key relationship.

PG docs on triggers: https://www.postgresql.org/docs/9.6/sql-createtrigger.html

W3 example: https://www.w3resource.com/PostgreSQL/postgresql-triggers.php

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.