Вычисляемые / вычисляемые столбцы в PostgreSQL

поддерживает ли PostgreSQL вычисляемые / вычисляемые столбцы, такие как MS SQL Server? Я ничего не могу найти в документах, но поскольку эта функция включена во многие другие СУБД, я подумал, что могу что-то пропустить.

например:http://msdn.microsoft.com/en-us/library/ms191250.aspx

5 ответов


PostgreSQL не поддерживает "вычисляемые столбцы"per se по крайней мере до Postgres 11.

посмотреть комментарий f90t о функции, находящейся в разработке, но это Не похоже, что это будет в Postgres 11, пока нет.

вы можете реализовать аналогичную функциональность с помощью посмотреть.

или вы можете использовать функции, которые работают и выглядят так же, как вычисляемые столбцы.
Подробный объяснение в этом связанном ответе:

"сохраненные" вычисляемые столбцы могут быть реализованы с помощью триггеры функционально идентичным образом.

материализованные представления - это тесно связанные понятия, реализовано с Postgres 9.3.
В более ранних версиях можно управлять MVs вручную.


да, вы можете!! решение должно быть легким, безопасным и эффективным...

Я новичок в postgresql, но, похоже, вы можете создавать вычисляемые столбцы с помощью индекс выражение в сочетании с посмотреть (вид не является обязательным, но делает жизнь немного легче).

предположим, что мои вычисления md5(some_string_field), тогда я создаю индекс, как:

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

теперь все запросы, которые действуют на MD5(some_string_field) будет использовать индекс вместо того, чтобы вычислять его с нуля. Например:

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

вы можете проверить это с помощью объяснить.

однако на данный момент Вы полагаетесь на пользователей таблицы, точно знающих, как построить столбец. Чтобы сделать жизнь проще, вы можете создать VIEW на дополненную версию исходной таблицы, добавив в вычисленное значение нового столбца:

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

теперь любые запросы с помощью some_table_augmented сможет использовать some_string_field_md5 без беспокоиться о том, как это работает..они просто получают хорошую производительность. Представление не копирует данные из исходной таблицы, поэтому оно хорошо работает как с памятью, так и с производительностью. Обратите внимание, однако, что вы не можете обновлять / вставлять в представление, только в исходную таблицу, но если вы действительно хотите, я считаю, что вы можете перенаправлять вставки и обновления в исходную таблицу с помощью правила (я могу ошибаться в этом последнем пункте, поскольку я никогда не пробовал его сам).

Edit: кажется если запрос включает конкурирующие индексы, механизм планирования может иногда вообще не использовать выражение-индекс. Выбор, по-видимому, зависит от данных.


один из способов сделать это с триггером!

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();

триггер запускается до обновления или вставки строки. Он изменяет поле, которое мы хотим вычислить из NEW запись, а затем возвращает эту запись.


У меня есть код, который работает и использует вычисляемый термин, я не на postgresSQL pure tho, который мы запускаем на PADB

вот как это использовать

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    ;

простое решение с ограничением Check:

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