[postgresql] Computed / calculated / virtual / derived columns in PostgreSQL

Does PostgreSQL support computed / calculated columns, like MS SQL Server? I can't find anything in the docs, but as this feature is included in many other DBMSs I thought I might be missing something.

Eg: http://msdn.microsoft.com/en-us/library/ms191250.aspx

The answer is


I have a code that works and use the term calculated, I'm not on postgresSQL pure tho we run on PADB

here is how it's used

create table some_table as
    select  category, 
            txn_type,
            indiv_id, 
            accum_trip_flag,
            max(first_true_origin) as true_origin,
            max(first_true_dest ) as true_destination,
            max(id) as id,
            count(id) as tkts_cnt,
            (case when calculated tkts_cnt=1 then 1 else 0 end) as one_way
    from some_rando_table
    group by 1,2,3,4    ;

A lightweight solution with Check constraint:

CREATE TABLE example (
    discriminator INTEGER DEFAULT 0 NOT NULL CHECK (discriminator = 0)
);

Well, not sure if this is what You mean but Posgres normally support "dummy" ETL syntax. I created one empty column in table and then needed to fill it by calculated records depending on values in row.

UPDATE table01
SET column03 = column01*column02; /*e.g. for multiplication of 2 values*/
  1. It is so dummy I suspect it is not what You are looking for.
  2. Obviously it is not dynamic, you run it once. But no obstacle to get it into trigger.

One way to do this is with a trigger!

CREATE TABLE computed(
    one SERIAL,
    two INT NOT NULL
);

CREATE OR REPLACE FUNCTION computed_two_trg()
RETURNS trigger
LANGUAGE plpgsql
SECURITY DEFINER
AS $BODY$
BEGIN
    NEW.two = NEW.one * 2;

    RETURN NEW;
END
$BODY$;

CREATE TRIGGER computed_500
BEFORE INSERT OR UPDATE
ON computed
FOR EACH ROW
EXECUTE PROCEDURE computed_two_trg();

The trigger is fired before the row is updated or inserted. It changes the field that we want to compute of NEW record and then it returns that record.


YES you can!! The solution should be easy, safe, and performant...

I'm new to postgresql, but it seems you can create computed columns by using an expression index, paired with a view (the view is optional, but makes makes life a bit easier).

Suppose my computation is md5(some_string_field), then I create the index as:

CREATE INDEX some_string_field_md5_index ON some_table(MD5(some_string_field));

Now, any queries that act on MD5(some_string_field) will use the index rather than computing it from scratch. For example:

SELECT MAX(some_field) FROM some_table GROUP BY MD5(some_string_field);

You can check this with explain.

However at this point you are relying on users of the table knowing exactly how to construct the column. To make life easier, you can create a VIEW onto an augmented version of the original table, adding in the computed value as a new column:

CREATE VIEW some_table_augmented AS 
   SELECT *, MD5(some_string_field) as some_string_field_md5 from some_table;

Now any queries using some_table_augmented will be able to use some_string_field_md5 without worrying about how it works..they just get good performance. The view doesn't copy any data from the original table, so it is good memory-wise as well as performance-wise. Note however that you can't update/insert into a view, only into the source table, but if you really want, I believe you can redirect inserts and updates to the source table using rules (I could be wrong on that last point as I've never tried it myself).

Edit: it seems if the query involves competing indices, the planner engine may sometimes not use the expression-index at all. The choice seems to be data dependant.


PostgreSQL 12 supports generated columns:

PostgreSQL 12 Beta 1 Released!

Generated Columns

PostgreSQL 12 allows the creation of generated columns that compute their values with an expression using the contents of other columns. This feature provides stored generated columns, which are computed on inserts and updates and are saved on disk. Virtual generated columns, which are computed only when a column is read as part of a query, are not implemented yet.


Generated Columns

A generated column is a special column that is always computed from other columns. Thus, it is for columns what a view is for tables.

CREATE TABLE people (
    ...,
    height_cm numeric,
    height_in numeric GENERATED ALWAYS AS (height_cm * 2.54) STORED
);

db<>fiddle demo


Examples related to postgresql

Subtracting 1 day from a timestamp date pgadmin4 : postgresql application server could not be contacted. Psql could not connect to server: No such file or directory, 5432 error? How to persist data in a dockerized postgres database using volumes input file appears to be a text format dump. Please use psql Postgres: check if array field contains value? Add timestamp column with default NOW() for new rows only Can't connect to Postgresql on port 5432 How to insert current datetime in postgresql insert query Connecting to Postgresql in a docker container from outside

Examples related to calculated-columns

The condition has length > 1 and only the first element will be used pandas dataframe create new columns and fill with calculated values from same df getting "No column was specified for column 2 of 'd'" in sql server cte? Computed / calculated / virtual / derived columns in PostgreSQL SQL Server String Concatenation with Null

Examples related to sql-view

Working with SQL views in Entity Framework Core Create view with primary key? Computed / calculated / virtual / derived columns in PostgreSQL SQL Views - no variables? Entity Framework and SQL Server View

Examples related to materialized-views

How to refresh materialized view in oracle Computed / calculated / virtual / derived columns in PostgreSQL What is the difference between Views and Materialized Views in Oracle?

Examples related to generated-columns

Computed / calculated / virtual / derived columns in PostgreSQL