Colonnes calculées / calculées en PostgreSQL

est-ce que PostgreSQL supporte les colonnes calculées / calculées, comme MS SQL Server? Je ne trouve rien dans les docs, mais comme cette fonctionnalité est incluse dans beaucoup D'autres DBMSs j'ai pensé que je pourrais manquer quelque chose.

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

49
demandé sur Erwin Brandstetter 2011-11-24 03:16:47

5 réponses

PostgreSQL ne supporte pas les "Colonnes Calculées" en soi jusqu'à au moins Postgres 11.

Voir f90t le commentaire de à propos de la fonction en cours de développement Mais il ne semble pas que cela va être dans Postgres 11 , encore.

vous pouvez implémenter une fonctionnalité similaire avec un view .

Ou vous pouvez utiliser fonctions cela fonctionne et ressemble juste aux colonnes calculées .

Explication détaillée dans cette réponse connexe:

"Persistantes" les colonnes calculées peuvent être mis en œuvre avec déclencheurs dans une fonctionnellement identiques.

vues Matérialisées sont étroitement liés concept, mis en œuvre depuis Postgresql 9.3 .

Dans les versions précédentes, on peut gérer MVS manuellement.

68
répondu Erwin Brandstetter 2018-06-28 13:21:55

OUI, vous le pouvez!! la solution doit être facile, sûre et performante...

je suis nouveau à postgresql, mais il semble que vous pouvez créer des colonnes calculées en utilisant un expression index , pair avec un view (la vue est facultative, mais rend la vie un peu plus facile).

supposons que mon calcul soit md5(some_string_field) , alors je crée l'index comme:

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

maintenant, toutes les requêtes qui agissent sur MD5(some_string_field) utiliseront l'index plutôt que de le calculer à partir de zéro. Par exemple:

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

vous pouvez vérifier cela avec expliquer .

cependant à ce point vous comptez sur les utilisateurs de la table savoir exactement comment construire la colonne. Pour rendre la vie plus facile, vous pouvez créer un VIEW sur une version augmentée de la table d'origine, en ajoutant la valeur calculée comme un nouvelle colonne:

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

désormais toutes les requêtes utilisant some_table_augmented pourront utiliser some_string_field_md5 sans se soucier de son fonctionnement..ils sont juste de bonnes performances. La vue ne copie aucune donnée de la table originale, donc elle est bonne pour la mémoire aussi bien que pour la performance. Notez toutefois que vous ne pouvez pas mettre à jour/insérer une vue, uniquement dans la table source, mais si vous voulez vraiment, je crois que vous pouvez rediriger les insertions et mises à jour de la table source à l'aide de règles (j'ai peut-être tort sur ce dernier point que je n'ai jamais essayé moi-même).

Edit: il semble que si la requête implique des indices de compétition, l'organisateur de moteur peut parfois ne pas utiliser l'expression de l'index. Le choix semble être données à charge.

15
répondu dan-man 2017-03-22 19:24:07

une façon de faire cela est avec un déclencheur!

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

le déclencheur est déclenché avant que la ligne ne soit mise à jour ou insérée. Il change le champ que nous voulons calculer de l'enregistrement NEW et ensuite il renvoie cet enregistrement.

12
répondu Elmer 2016-10-06 14:01:44

j'ai un code qui fonctionne et utilise le terme calculé, Je ne suis pas sur postgresSQL pure tho nous courons sur PADB

voici comment il est utilisé""

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    ;
1
répondu Wired604 2018-06-12 15:37:14

Une solution légère et avec la contrainte de Vérification:

CREATE TABLE example (
    discriminator INTEGER DEFAULT 0 NOT NULL CHECK (discriminator = 0)
);
-2
répondu cinereo 2013-08-18 16:26:51