Passer une liste a une fonction? - SQL/NoSQL - Programmation
Marsh Posté le 23-10-2007 à 18:03:14
Il faudrait indiquer quelle base de données est utilisée car ce n'est pas du SQL standard.
Dans les manuel d'Oracle, cela s'appelle faire du "Dynamic SQL".
Comme, cela n'était pas très facile à mettre en oeuvre, j'avais adopté une autre méthode consistant reporter cette flexibilité dans le programme qui appelle SQL en construisant une requête à géométrie variable.
Marsh Posté le 23-10-2007 à 18:13:42
J'utilise une base de donnee Oracle et j'y accede avec un programme Java.
Marsh Posté le 24-10-2007 à 10:31:35
Je déconseille le "dynamic sql".
Autant faire tourner ce genre de requêtes depuis Java, pour une tétrachiée de raisons.
Par contre.
Normalement, tu dois pouvoir travailler avec une table temporaire dans une PS.
Je te conseille donc d'attendre un VARCHAR2(4000) en entrée, qui contient tes mots "bruts" séparés par un séparateur reconnaissable (virgule, pipe, ce que tu veux).
Ensuite, du boule dessus à l'aide de fonctions substr() et instr(), afin d'alimenter ta table temporaire avec chaque mot de la liste.
Ensuite tu peux simplement faire :
select ...
from ...
where mocle in (select mot from listemotscles)
Marsh Posté le 24-10-2007 à 10:33:24
Je ne me souviens plus si Oracle accete le type de retour "table". Et si oui, à partir de quelle version.
Si c'est le cas, en tout cas je te conseille de modulariser le truc en faisant une fonction "split()", qui à partir d'une liste et d'un séparateur, te retourne une table contenant la liste des mots de la liste.
C'est ce que j'avais fais sous SQL Server 2000 en réponse à un problème similaire.
Marsh Posté le 26-10-2007 à 22:54:14
Pour avoir moi même utiliser cette méthode dans des procstocks sur une grosse BdD SQL Server 2005 je confirme que c'est une bonne approche.
Je ne sais pas ce qu'il en est sous Oracle, mais dans notre cas ça marche très bien, on a factorisé le truc sous forme de fonction. Ainsi ça s'utilise avec
.... Where macouille IN (select * from splitChaineToTable(@monVarchar)) ...
Il y a une autre possibilité, tout à fait immonde en terme de maintenance du code, mais fonctionnelle.
Tu stockes toute ta requete dans une chaine et tu fais un gros exec à la fin. C'est moche, illisible, pourri, mais ça marche à la perfection.
Illustration :
Declare @req varchar(500);
Set @req = 'select ... where Id in (' + @monVarchar + ');
Exec @req;
Ainsi au passage le sgbdr perd la notion de ce qui était ou non une chaîne, et n'a plus qu'une requête banale à faire tourner.
Bon, staffreux hein
mais ça marche et ça demande aucun travail cérébral.
Marsh Posté le 28-10-2007 à 07:36:50
Ouais, c'est la solution qu'avait proposé Olivthill sous le nom de "Dynamic SQL".
Effectivement, ça marche, mais outre les points négatifs que tu cites, il y en a d'autres, tels que les risques de SQL Injection, mais aussi (et surtout) le fait que la requête est alors "inconnue" au moment de son exécution, et nécessite une analyse complète avant d'être exécutée.
Ainsi, ta procédure stockée n'apporte rien d'un point de vue performance ou sécurité, ce qui est un peu domage, vu que c'est les deux plus gros avantages de PS...
C'est pourquoi j'avais conseillé, quite à faire une requête dynamique, de la faire depis Java, qui est plus aisé à programmer que le PL/SQL, et où ce genre d'horreur dérange moins
Marsh Posté le 28-10-2007 à 12:14:39
Pour ce qui est du risque d'injection sql, je le considérais comme nul car à mon avis une liste de valeurs à passer à une requête sous la forme qu'on entendait doit nécessairement être construite par code, par concaténation des id du groupe d'éléments à manipuler par exemple si c'est le genre de traitement visé. Là apparemment il s'agirait plutôt d'une liste de chaîne, mais le raisonnement reste valable.
Je n'envisageais même pas qu'on puisse exploiter une liste fournie à la main par l'utilisateur (par exemple, pour donner un cas concret où il y a risque d'injection), surtout sans y faire aucune validation, ce qui même sans parler d'injection "volontaire" serait purement suicidaire (la moindre erreur de syntaxe et le truc se viande, et on sait bien qu'un utilisateur n'est jamais fiable).
Mais sinon on est d'accord sur toute la ligne hein
Marsh Posté le 23-10-2007 à 17:04:51
Bonjour,
je souhaite passer une liste de mot a une fonction SQL. J'aimerais ensuite utiliser la liste de mot dans un test IN. Toutefois je n'arrive pas a trouver une facon de passer ma liste de mot a ma fonction : j'ai essaye de la mettre dans un VARCHAR2 mais le logiciel ne veut pas car il voit que c'est une liste.
Des idees sur comment resoudre ce probleme?
Merci !