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
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.
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.
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.
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 ;
Une solution légère et avec la contrainte de Vérification:
CREATE TABLE example (
discriminator INTEGER DEFAULT 0 NOT NULL CHECK (discriminator = 0)
);