Précédent   Forum des professionnels en informatique > Bases de données > Langage SQL
Langage SQL Forum d'entraide sur le langage SQL et sur les questions liées à la conception de schéma (DDL). Cours SQL
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 10/08/2011, 14h59   #1
Invité régulier
 
Inscription : février 2007
Messages : 17
Détails du profil
Informations forums :
Inscription : février 2007
Messages : 17
Points : 5
Points : 5
Par défaut Fonction avec nombre variable de paramètres et utilisation de ceux-ci

Bonjour à tous,

Voici mon problème :
Je dois créer une fonction qui prend en paramètre un nombre variable d'identifiants (numériques).
Cette même fonction doit vérifier si ces identifiants existent dans une table et afficher les données correspondantes.

Moyennant une astuce, j'ai réussi à faire ce que je voulais. Mais ce n'est pas très efficient et j'aimerais une meilleure façon de le réaliser.

Voici donc ce à quoi je suis arrivé :

Code :
1
2
3
4
5
6
7
8
9
10
11
 
CREATE OR REPLACE FUNCTION fct(listeIDs text)
  RETURNS SETOF record AS
$$
SELECT DISTINCT annee, id
FROM myTable
WHERE 
	$1 LIKE '%,' || CAST(id AS TEXT) || ',%'
GROUP BY annee, id
$$
  LANGUAGE sql;
La fonction reçoit un tableau d'identifiant sous forme de texte et va rechercher dans la table "myTable" les champs "annee" et "id" lorsqu'on retrouve id dans le texte entré en paramètre (entre virgules en fait, car il s'agit d'un tableau).

Un petit exemple d'appel à cette fonction :
Code :
1
2
 
SELECT * FROM fct('[,4504,6229,5,6,]') AS (Annee numeric, Id numeric);
Juste pour info, mais pas nécessaire :
j'ai simplement ajouté des virgules autour des premiers et derniers identifiants afin que si l'on cherche '2', il ne soit pas trouvé dans '6229'.

Si vous avez une meilleure façon de réaliser cela, je suis preneur.
Merci d'avance pour votre aide et vos conseils...
johnalias110 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/08/2011, 15h43   #2
Membre émérite
 
Homme Olivier Dehorter
Ingenieur de recherche - Ecologue
Inscription : juin 2003
Messages : 697
Détails du profil
Informations personnelles :
Nom : Homme Olivier Dehorter
Localisation : France

Informations professionnelles :
Activité : Ingenieur de recherche - Ecologue

Informations forums :
Inscription : juin 2003
Messages : 697
Points : 837
Points : 837
bonjour,

je pense que ceci peut t'aider. J'ai trouve cela sur un forum (mais je ne sais plus ou et par qui Aussi je m'excuse d'avance auprès du créateur).

Cela fonctionne sous FIREBIRD, donc à adapter selon ton SGBD

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
 
CREATE OR ALTER PROCEDURE Tokenize (
    Entree        VARCHAR(1024),
    Token         CHAR(1),
    Vide_Possible SMALLINT)
RETURNS (
    Result VARCHAR(255))
AS
  DECLARE VARIABLE Newpos INTEGER;
  DECLARE VARIABLE Oldpos INTEGER;
BEGIN --Revoie les lignes d'une chaine de carateres separes par un token
    IF (vide_possible NOT BETWEEN 0 AND 1) then
       vide_possible = 1;
    Oldpos = 1;
    Newpos = 1;
    WHILE (1 = 1) DO
    BEGIN
        Newpos = POSITION(Token, Entree, Oldpos);
        IF (Newpos > 0) THEN
        BEGIN
            Result = Trim(SUBSTRING(Entree FROM Oldpos FOR Newpos - Oldpos));
            IF (NOT ((result = '') AND (vide_possible = 0))) then
               SUSPEND;
            Oldpos = Newpos + 1;
        END
        ELSE
        IF (Oldpos - 1 < CHAR_LENGTH(Entree)) THEN
        BEGIN
            IF (NOT ((result = '') AND (vide_possible = 0))) then
               Result = Trim(SUBSTRING(Entree FROM Oldpos));
            SUSPEND;
            BREAK;
        END
        ELSE
        BEGIN
            BREAK;
        END
    END
END
dehorter olivier est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/08/2011, 22h30   #3
Modérateur
 
Inscription : octobre 2008
Messages : 1 508
Détails du profil
Informations personnelles :
Localisation : France, Paris (Île de France)

Informations forums :
Inscription : octobre 2008
Messages : 1 508
Points : 2 040
Points : 2 040
D'après la déclaration de fonction, le SGBD est PostgreSQL. Depuis la version 8.4 les nombres variables d'arguments sont supportés par les fonctions.

Si ID est de type numeric, la déclration pourrait ressembler à:
Code :
1
2
3
4
5
CREATE OR REPLACE FUNCTION fct(variadic numeric[]) RETURNS SETOF record 
AS $$
SELECT annee, id FROM myTable WHERE id =ANY($1)
  GROUP BY annee, id
$$  LANGUAGE sql;
La syntaxe de l'appel serait du style:
Code :
SELECT * FROM fct(4504,6229,5,6) AS (Annee numeric, Id numeric);
Si c'est une version de postgres 8.3 ou inférieur, il faut enlever variadic de la déclaration de fonction et l'appeler comme ça:
Code :
SELECT * FROM fct(array[4504,6229,5,6]) AS (Annee numeric, Id numeric);
estofilo est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 11/08/2011, 11h38   #4
Invité régulier
 
Inscription : février 2007
Messages : 17
Détails du profil
Informations forums :
Inscription : février 2007
Messages : 17
Points : 5
Points : 5
Déjà, merci pour vos réponses.

J'ai regardé en vitesse l'éventuelle solution de dehorter olivier, qui me semble légèrement plus compliquée. Je précise, pour les futurs lecteurs de ce post, que je ne l'ai pas essayée

Pour estofilo, en effet, j'utilise PostgreSQL. L'idée de base était de créer des fonctions qui aurait permis de passer d'un SGBD à l'autre en cas de migration. Mais bon, comme on le sait, ceux-ci ne s'entendent pas toujours sur les normes et donc c'est parfois bien difficile !

J'avais pensé à utiliser "variadic", mais cela me limitait dans le nombre de paramètres (100 maximum) et comme je ne suis pas maître de ce nombre, ca ne me convenait pas tellement...
Par contre, j'ai essayé le même fonctionnement en utilisant "array" et là, pas de limitation... ! Du coup, cette solution me convient beaucoup mieux !

Alors, une dernière petite question, bien que le sujet soit résolu : est-ce qu'utiliser array dans ce cas-ci est deprecated depuis la version 8.4 ou est-ce que variadic est une alternative ?

Encore merci !
johnalias110 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 11/08/2011, 13h25   #5
Modérateur
 
Inscription : octobre 2008
Messages : 1 508
Détails du profil
Informations personnelles :
Localisation : France, Paris (Île de France)

Informations forums :
Inscription : octobre 2008
Messages : 1 508
Points : 2 040
Points : 2 040
Citation:
Alors, une dernière petite question, bien que le sujet soit résolu : est-ce qu'utiliser array dans ce cas-ci est deprecated depuis la version 8.4 ou est-ce que variadic est une alternative ?
A mon sens, il n'y a aucune inquiétude à avoir sur la pérennité d'aucune des 2 formes.
estofilo est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 11/08/2011, 14h12   #6
Invité régulier
 
Inscription : février 2007
Messages : 17
Détails du profil
Informations forums :
Inscription : février 2007
Messages : 17
Points : 5
Points : 5
Merci !
johnalias110 est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 08h55.


 
 
 
 
Partenaires

Hébergement Web