Czy PostgreSQL obsługuje kolumny obliczeniowe / obliczeniowe, takie jak MS SQL Server? Nie mogę znaleźć niczego w dokumentacji, ale ponieważ ta funkcja jest zawarta w wielu innych systemach DBMS, pomyślałem, że mogę czegoś przegapić.
Czy PostgreSQL obsługuje kolumny obliczeniowe / obliczeniowe, takie jak MS SQL Server? Nie mogę znaleźć niczego w dokumentacji, ale ponieważ ta funkcja jest zawarta w wielu innych systemach DBMS, pomyślałem, że mogę czegoś przegapić.
Odpowiedzi:
Kolumny generowane do Postgres 11 nie są obsługiwane - zgodnie ze standardem SQL i implementowanymi przez niektóre RDBMS, w tym DB2, MySQL i Oracle. Ani podobne „kolumny obliczeniowe” SQL Server.
STORED
wygenerowane kolumny są wprowadzane w Postgres 12 . Trywialny przykład:
CREATE TABLE tbl (
int1 int
, int2 int
, product bigint GENERATED ALWAYS AS (int1 * int2) STORED
);
db <> skrzypce tutaj
VIRTUAL
wygenerowane kolumny mogą zawierać jedną z następnych iteracji. (Jeszcze nie w Postgres 13).
Związane z:
Do tego czasu można emulować VIRTUAL
kolumny generowane za pomocą funkcji używającej notacji atrybutu ( tbl.col
), która wygląda i działa podobnie jak wirtualna kolumna generowana . To trochę dziwaczna składnia, która istnieje w Postgres z powodów historycznych i pasuje do przypadku. Ta powiązana odpowiedź zawiera przykłady kodu :
Wyrażenie (wyglądające jak kolumna) nie jest jednak zawarte w a SELECT * FROM tbl
. Zawsze musisz to wyraźnie wymienić.
Może być również obsługiwany za pomocą pasującego indeksu wyrażenia - pod warunkiem, że funkcja jest IMMUTABLE
. Lubić:
CREATE FUNCTION col(tbl) ... AS ... -- your computed expression here
CREATE INDEX ON tbl(col(tbl));
Alternatywnie możesz zaimplementować podobną funkcjonalność za pomocą VIEW
, opcjonalnie w połączeniu z indeksami wyrażeń. Następnie SELECT *
można dołączyć wygenerowaną kolumnę.
STORED
Kolumny obliczane „Persisted” ( ) można zaimplementować z wyzwalaczami w funkcjonalnie identyczny sposób.
Widoki zmaterializowane to ściśle związana koncepcja, wprowadzona od Postgres 9.3 .
We wcześniejszych wersjach można ręcznie zarządzać MV.
Tak, możesz!! Rozwiązanie powinno być łatwe, bezpieczne i wydajne ...
Jestem nowy w postgresql, ale wygląda na to, że możesz tworzyć kolumny obliczone za pomocą indeksu wyrażeń w połączeniu z widokiem (widok jest opcjonalny, ale sprawia, że życie jest trochę łatwiejsze).
Załóżmy, że moje obliczenia to md5(some_string_field)
, a następnie tworzę indeks jako:
CREATE INDEX some_string_field_md5_index ON some_table(MD5(some_string_field));
Teraz wszelkie zapytania, na podstawie których działają, MD5(some_string_field)
będą używać indeksu, zamiast obliczać go od zera. Na przykład:
SELECT MAX(some_field) FROM some_table GROUP BY MD5(some_string_field);
Możesz to sprawdzić, wyjaśniając .
Jednak w tym momencie polegasz na tym, że użytkownicy tabeli wiedzą dokładnie, jak zbudować kolumnę. Aby ułatwić sobie życie, możesz utworzyć VIEW
rozszerzoną wersję oryginalnej tabeli, dodając obliczoną wartość jako nową kolumnę:
CREATE VIEW some_table_augmented AS
SELECT *, MD5(some_string_field) as some_string_field_md5 from some_table;
Teraz wszystkie zapytania, które używają, some_table_augmented
będą mogły być używane some_string_field_md5
bez martwienia się o to, jak to działa… Po prostu uzyskują dobrą wydajność. Widok nie kopiuje żadnych danych z oryginalnej tabeli, więc jest dobry zarówno pod względem pamięci, jak i wydajności. Pamiętaj jednak, że nie możesz aktualizować / wstawiać do widoku, tylko do tabeli źródłowej, ale jeśli naprawdę chcesz, uważam, że możesz przekierować wstawki i aktualizacje do tabeli źródłowej za pomocą reguł (mogę się mylić w tym ostatnim punkcie, ponieważ Sam nigdy tego nie próbowałem).
Edycja: wydaje się, że jeśli zapytanie dotyczy konkurencyjnych indeksów, silnik planowania może czasami w ogóle nie używać indeksu wyrażenia. Wybór wydaje się zależeć od danych.
if the query involves competing indices
?
Jednym ze sposobów jest użycie spustu!
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();
Wyzwalacz jest uruchamiany przed aktualizacją lub wstawieniem wiersza. Zmienia pole, które chcemy obliczyć na NEW
rekord, a następnie zwraca ten rekord.
insert into computed values(1, 2); insert into computed values(4, 8); commit; select * from computed;
i właśnie wróciło: 1 2 i 4 8
insert into computed(one) values(1); insert into computed(one) values(4); commit; select * from computed;
wartość two
kolumny zostanie obliczona automagicznie!
PostgreSQL 12 obsługuje generowane kolumny:
Wygenerowane kolumny
PostgreSQL 12 umożliwia tworzenie generowanych kolumn, które obliczają ich wartości za pomocą wyrażenia wykorzystującego zawartość innych kolumn. Ta funkcja zapewnia przechowywane wygenerowane kolumny, które są obliczane na wstawkach i aktualizacjach oraz zapisywane na dysku. Wirtualne kolumny generowane, które są obliczane tylko wtedy, gdy kolumna jest odczytywana jako część zapytania, nie są jeszcze zaimplementowane.
Kolumna generowana to specjalna kolumna, która jest zawsze obliczana na podstawie innych kolumn. Zatem dla kolumn jest tym, czym widok dla tabel.
CREATE TABLE people (
...,
height_cm numeric,
height_in numeric GENERATED ALWAYS AS (height_cm * 2.54) STORED
);
Cóż, nie jestem pewien, czy to masz na myśli, ale Posgres normalnie obsługuje "fikcyjną" składnię ETL. Utworzyłem jedną pustą kolumnę w tabeli, a następnie musiałem wypełnić ją obliczonymi rekordami w zależności od wartości w wierszu.
UPDATE table01
SET column03 = column01*column02; /*e.g. for multiplication of 2 values*/
Mam kod, który działa i używam obliczonego terminu, nie korzystam z czystego PostgresSQL, chociaż uruchamiamy na PADB
oto jak jest używany
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 ;
Lekkie rozwiązanie z ograniczeniem Sprawdź:
CREATE TABLE example (
discriminator INTEGER DEFAULT 0 NOT NULL CHECK (discriminator = 0)
);
field as 1 persisted
.