If you have a generated column in PostgreSQL, you can use the following methods to find the definition of that column.
The \d
Command
In psql, the \d
command shows information about tables, views, materialised views, index, sequences, or foreign tables. It includes a column that contains the definition of any generated columns:
\d students
Result:
Table "public.students" Column | Type | Collation | Nullable | Default -----------+------------------------+-----------+----------+----------------------------------------------------------------------------------- id | integer | | not null | firstname | character varying(50) | | | lastname | character varying(50) | | | fullname | character varying(101) | | | generated always as ((((firstname::text || ' '::text) || lastname::text))) stored Indexes: "students_pkey" PRIMARY KEY, btree (id)
We can see that the fullname
column is a generated column, and that the Default
column contains its expression.
In this case, the expression looks like this:
generated always as ((((firstname::text || ' '::text) || lastname::text))) stored
That expression reflects the code that was used to create the generated column. We can see that it’s a stored column (as opposed to virtual).
- A stored generated column stores its value in the table (and therefore uses up space in the table).
- A virtual generated column generates its value dynamically when the table is read.
As of PostgreSQL 14, PostgreSQL only supports stored generated columns. This could change in a future release.
The information_schema.columns
View
The information_schema.columns
view contains information about columns. It includes a generation_expression
column that contains the expression of any generated columns:
SELECT
column_name,
is_generated,
generation_expression
FROM information_schema.columns
WHERE table_name = 'students';
Result:
column_name | is_generated | generation_expression -------------+--------------+-------------------------------------------------------- id | NEVER | firstname | NEVER | lastname | NEVER | fullname | ALWAYS | (((firstname)::text || ' '::text) || (lastname)::text)
It also contains the is_generated
column, which I returned here. This simply tells us whether or not it’s a generated column.