L'exécution de requêtes dynamiquement en PL/pgSQL.
J'ai trouvé des solutions (je crois) pour le problème, je suis sur le point de demander à Oracle et SQL Server, mais n'arrive pas à le traduire dans un Postgres solution. J'utilise Postgres 9.3.6.
L'idée est d'être capable de générer des "métadonnées" sur le contenu de la table à des fins de profilage. Ceci ne peut être fait (à ma connaissance) en ayant les requêtes exécutées pour chaque colonne de manière à savoir, dire... min/max/le comte de valeurs et de ces. Afin d'automatiser la procédure, il est préférable d'avoir les requêtes générées par la DB, puis exécutés.
Avec un exemple salesdata
table, je suis en mesure de générer une requête de sélection pour chaque colonne, de retour de la fonction min() valeur à l'aide de l'extrait de code suivant:
SELECT 'SELECT min('||column_name||') as minval_'||column_name||' from salesdata '
FROM information_schema.columns
WHERE table_name = 'salesdata'
L'avantage étant que la db va générer le code quel que soit le nombre de colonnes.
Maintenant, il y a une multitude d'endroits où j'avais à l'esprit pour le stockage de ces requêtes, soit une variable quelconque, ou une colonne de table, l'idée étant de faire exécuter ces requêtes.
J'ai pensé à stocker les requêtes générées dans une variable puis de les exécuter à l'aide de la EXECUTE
(ou EXECUTE IMMEDIATE
) une déclaration qui est l'approche employée ici (voir le volet de droite), mais Postgres ne me permet pas de déclarer une variable en dehors d'une fonction et j'ai été de me gratter la tête à la façon d'ajustement entre eux, que c'est même la direction à suivre, peut-être il y a quelque chose de plus simple.
Avez-vous des pointeurs, je suis en train d'essayer quelque chose de ce genre, inspiré par cette autre question mais n'ai aucune idée si je suis dans la bonne direction:
CREATE OR REPLACE FUNCTION foo()
RETURNS void AS
$$
DECLARE
dyn_sql text;
BEGIN
dyn_sql := SELECT 'SELECT min('||column_name||') from salesdata'
FROM information_schema.columns
WHERE table_name = 'salesdata';
execute dyn_sql
END
$$ LANGUAGE PLPGSQL;
- C'est vraiment pas clair ce que vous essayez de faire. Générer des chaînes de requête pour les sauver? Exécuter des requêtes et d'enregistrer les résultats? Veuillez préciser la tâche. Et, comme toujours, de donner votre version de Postgres, s'il vous plaît.
- "pour des fins de profilage" --- qu'est-ce exactement que la moyenne?
- Qu'aimeriez-vous votre fonction de retour? Le minimum de chaque colonne?
- Il n'y a pas de
EXECUTE IMMEDIATE
en plpgsql, justeEXECUTE
. - profilage des données est un moyen d'obtenir une bonne idée de ce qui est dans votre tableau, min/max/moyenne des valeurs, la valeur des fréquences, la valeur de la distribution, comte de valeurs null, etc... c'est un point de départ pour les données d'évaluation de la qualité.
- J'ai aussi répondu à la question qui vous a inspiré: stackoverflow.com/a/29616496/939860
Vous devez vous connecter pour publier un commentaire.
Système de statistiques
Avant de vous lancer à votre propre compte, ont un coup d'oeil à la table système
pg_statistic
ou la vuepg_stats
:Il peut déjà avoir les statistiques, vous êtes sur le point de calcul. Elle est remplie par
ANALYZE
, de sorte que vous pouvez exécuter que pour les nouveaux (ou aucun) des tables avant de les vérifier.Générique dynamique plpgsql fonction
Il semble que vous voulez retourner à la valeur minimale pour chaque colonne dans un tableau. Ce n'est pas une tâche triviale, parce que d'une fonction (comme SQL en général) demande de connaître le type de retour au moment de la création - ou au moins à l'heure de l'appel avec l'aide du polymorphisme des types de données
Cette fonction fait tout automatiquement et en toute sécurité. Fonctionne pour tout table, aussi longtemps que la fonction d'agrégation
min()
est autorisé pour chaque colonne. Mais vous besoin de connaître votre chemin autour plpgsql.Appel:
SQL Violon.
Vous avez besoin de comprendre ces concepts:
EXECUTE
.Liées réponse avec explication détaillée:
Difficulté particulière avec d'incompatibilité de type
Je profite de Postgres la définition d'un type de ligne pour chaque table existante. En utilisant le concept de types polymorphes je suis en mesure de créer un fonction qui fonctionne pour tout le tableau.
Cependant, certaines fonctions d'agrégat de retour liés mais différents types de données, comme par rapport à la colonne sous-jacente. Par exemple,
min(varchar_column)
retournetext
, ce qui est peu compatible, mais pas exactement le même type de données. plpgsql fonctions ont un point faible ici et d'insister sur les types de données exactement comme déclaré dans leRETURNS
clause. Aucune tentative de le jeter, même pas conversions implicites, pour ne pas parler d'attribution de jette.Qui devraient être améliorés. Testé avec Postgresql 9.3. Ne pas refaire le test avec 9.4, mais je suis assez sûr, rien n'a changé dans ce domaine.
C'est là que cette construction vient:
Semble tordu à la première. C'est le solution de contournement: Par la coulée de l'ensemble de la ligne à la ligne type de la table sous-jacente explicitement nous la force d'attribution de jette pour obtenir un exemplaire original des types de données pour chaque colonne.
Être conscient que cela peut échouer pour certaines fonction d'agrégation.
sum()
retournenumeric
pour unsum(bigint_column)
pour accueillir pour une somme déborder le type de données de base. Casting de retour àbigint
peut échouer ...@Erwin Brandstetter, merci Beaucoup pour la réponse. pg_stats est en effet un peu les choses, mais ce que j'ai vraiment besoin de dessiner un profil complet est une variété de choses, min, max), compte, comte de valeurs null, moyenne etc... donc, un tas de requêtes doivent être couru pour chacune des colonnes, certaines avec de GROUPE PAR exemple.
Aussi, merci pour mettre en évidence l'importance des types de données, j'ai été en quelque sorte d'attendre cela de jeter une clé dans les travaux à un certain point, ma principale préoccupation était de savoir comment automatiser la génération de requêtes, et à son exécution, ce dernier étant ma principale préoccupation.
J'ai essayé la fonction que vous fournissez (je vais probablement besoin d'apprendre quelques plpgsql), mais une erreur au SELECT (t::tbl) :
btw, qu'est-ce que le (t::abc) notation appelée, en python, ce serait une liste de tranche, mais c'est probablement pas le cas en PLPGSQL
t::abc
: stackoverflow.com/a/13676871/939860