PostgreSQL La base de donnees la plus sophistiquee au monde.

Forums PostgreSQL.fr

Le forum officiel de la communauté francophone de PostgreSQL

Vous n'êtes pas identifié(e).

#1 22/02/2021 18:45:12

sousou
Membre

merci de déplacer dans la bonne catégorie svp

Bonjour, je cherche a creer une fonction qui prends en paramètre un nom de table et qui vérifie si la table existe bien, dans le cas ou elle existe, affiche le nombre de ligne de la table.
Voici le code que j'ai pour l'instant :

create or replace function comptageLignes(varchar) returns integer AS $$
DECLARE
nombreLignes integer;
BEGIN

//Passage qui doit verifier si la table existe, si non retourner 0 ou un message d'erreur.
.....
......

//Ensuite le cas ou la table existe :
    EXECUTE 'SELECT COUNT(*) FROM ' || $1 INTO nombreLignes;
    RETURN nombreLignes;
END;
$$ language PLPGSQL;

Je ne parviens pas à vérifier l'existance de la table puisque le nom de la table est passé en paramètre donc je dois forcément utiliser un EXECUTE mais impossible d'utiliser EXECUTE avec un IF ou un PERFORM.
Merci d'avance pour vos réponses

Dernière modification par sousou (22/02/2021 18:49:29)

Hors ligne

#2 22/02/2021 18:49:48

rjuju
Administrateur

Re : merci de déplacer dans la bonne catégorie svp

Bonjour,


Je ne suis pas certain de comprendre votre soucis avec EXECUTE / IF / PERFORM.  Avez-vous un bout de code avec l'erreur générée ?

Hors ligne

#3 22/02/2021 18:56:35

sousou
Membre

Re : merci de déplacer dans la bonne catégorie svp

En fait ce que j'aimerai faire ca serait ca :

create or replace function comptageLignes(nomtable varchar) returns integer AS $$
DECLARE
nombreLignes integer;
BEGIN
    IF EXISTS (execute 'SELECT COUNT(*) FROM ' || $1) THEN
           execute 'SELECT COUNT(*) FROM ' || $1 INTO nombreLignes;
               return nombreLignes;
    else
           return 0;
    end if;

END;
$$ language PLPGSQL;

Donc je voudrais tester l'existence de la table dans le IF, si elle existe afficher le nombre de lignes dans la table, dans le cas contraire retourner 0

Ce que j'ai en affichage : ERREUR:  erreur de syntaxe sur ou près de « execute »
LIGNE 47 :  IF EXISTS (execute 'SELECT COUNT(*) FROM ' || $1) THEN

Dernière modification par sousou (22/02/2021 18:57:16)

Hors ligne

#4 22/02/2021 19:39:16

rjuju
Administrateur

Re : merci de déplacer dans la bonne catégorie svp

Ah je comprend mieux.  Pour tester l'existence de la table, vous devriez chercher directement l'existence d'une ligne correspondante dans les catalogues postgres (voir https://docs.postgresql.fr/13/catalog-pg-class.html et https://docs.postgresql.fr/13/view-pg-tables.html ).


Vous pouvez du coup effecuter un SELECT count(*) INTO pour récupérer le nombre d'enregistrement dans les catalogues pour vérifier l'existence de la table.


Attention cependant, votre fonction a énormément de problèmes :

- la concaténation permet des injections SQL, c'est une faille de sécurité
- vous utilisez un nom de table non qualifié, que se passe-t-il si plusieurs tables du même nom existent dans différents schéma, et que se passe-t-il si vous changer le(s) schémas par défaut ?
- un COUNT(*) peut potentiellement être très long.  Avez-vous besoin d'un nombre exact ou d'une estimation ?  La colonne reltuples de pg_class pourrait par exemple être une alternative
- vous utilisez un integer pour le nombre de lignes, mais votre table pourrait contenir bien plus de ligne que ce que permet de stocker un integer
- votre fonction ne permet pas de différencier une table vide d'une table qui n'existe pas

Hors ligne

#5 23/02/2021 22:21:29

sousou
Membre

Re : merci de déplacer dans la bonne catégorie svp

Select count(*) into

Bonsoir, donc supposons que je souhaite faire une fonction qui vérifie uniquement l'existance d'une table, avec son nom passé en paramètre.
(sans prendre en compte les contraintes ou complication ou nombre de ligne trop élevé)
Cela donnerai :

create or replace function verifExistTable (varchar) returns integer AS $$
DECLARE
nombreLignes integer;
BEGIN
     /*que dois je mettre ici ?*/
END;
$$ language PLPGSQL;


requete que je tape :
select comptageLignes('Bookbay.auteurs');

Dois je utiliser :  reltuples float4 ?

Merci d'avance

Dernière modification par sousou (23/02/2021 23:11:32)

Hors ligne

#6 24/02/2021 13:52:56

sousou
Membre

Re : merci de déplacer dans la bonne catégorie svp

Bonjour, voila ce que j'aimerai que la fonctions fasse.

create or replace function comptageLignes(nomtable varchar) returns integer AS $$
DECLARE
nombreLignes integer;
BEGIN

    PERFORM (EXECUTE 'SELECT COUNT(*) FROM ' || $1);
    if (FOUND is false) then
        return false;
    else
            EXECUTE 'SELECT COUNT(*) FROM ' || $1 INTO nombreLignes;
            return nombreLignes;
    end if;

END;
$$ language PLPGSQL;

Cela dit la ligne avec le PERFORM et le EXECUTE n'est pas faisable et me renvoie une erreur.
Il y aurait un autre equivalent correct à cette ligne ?

Merci d'avance

Hors ligne

#7 24/02/2021 14:49:58

rjuju
Administrateur

Re : merci de déplacer dans la bonne catégorie svp

Il ne faut pas essayer de faire un "SELECT COUNT(*) FROM latable", sinon vous aurez une erreur si la table n'existe pas.  Comme indiqué précédemment :

Pour tester l'existence de la table, vous devriez chercher directement l'existence d'une ligne correspondante dans les catalogues postgres (voir https://docs.postgresql.fr/13/catalog-pg-class.html et https://docs.postgresql.fr/13/view-pg-tables.html ).

Vous pouvez du coup effecuter un SELECT count(*) INTO pour récupérer le nombre d'enregistrement dans les catalogues pour vérifier l'existence de la table.

Vous pouvez également consulter https://docs.postgresql.fr/13/plpgsql-declarations.html pour plus de détails sur la syntaxe, notamment les paragraphes §42.5.3 et §42.5.4 pour des exemples d'assignation de variable avec des requêtes statiques et dynamiques.  Dans votre cas en requêtant le catalogue pour trouver une ligne correspondante à votre table vous pouvez utiliser une requête statique et utiliser directement la variable pour la clause WHERE.

Hors ligne

Pied de page des forums