J'ai une liste de python, dis l
l = [1,5,8]
Je veux écrire une requête SQL pour obtenir les données de tous les éléments de la liste, disons
select name from students where id = |IN THE LIST l|
Comment faire cela?
Jusqu'à présent, les réponses ont été des modèles de valeurs dans une chaîne SQL simple. C'est tout à fait correct pour les entiers, mais si nous voulions le faire pour les chaînes, nous obtenons le problème d'échappement.
Voici une variante utilisant une requête paramétrée qui fonctionnerait pour les deux:
placeholder= '?' # For SQLite. See DBAPI paramstyle.
placeholders= ', '.join(placeholder for unused in l)
query= 'SELECT name FROM students WHERE id IN (%s)' % placeholders
cursor.execute(query, l)
','.join(placeholder * len(l))
serait un peu plus court tout en restant lisible à mon humble avis([placeholder]*len(l))
dans le cas général car l'espace réservé peut être composé de plusieurs caractères.cursor.execute(f'SELECT name FROM students WHERE id IN ({','.join('?' for _ in l)})', l)
. @bobince, vous devriez également remarquer dans votre solution que l'utilisation?
est le moyen le plus sûr d'éviter l'injection SQL. Il y a beaucoup de réponses ici qui sont vulnérables, essentiellement celles qui concaténent des chaînes en python.Le moyen le plus simple est de transformer la liste en
tuple
premierla source
Ne le compliquez pas, la solution est simple.
J'espère que cela a aidé !!!
la source
l
ne contient qu'un seul élément, vous vous retrouverez avecid IN (1,)
. Ce qui est une erreur de syntaxe.sqlite3
. Avec quelle bibliothèque avez-vous testé cela?Le SQL que vous voulez est
Si vous voulez construire cela à partir du python, vous pouvez utiliser
La fonction map transformera la liste en une liste de chaînes qui peuvent être collées ensemble par des virgules à l'aide de la méthode str.join .
Alternativement:
si vous préférez les expressions génératrices à la fonction map.
MISE À JOUR: S. Lott mentionne dans les commentaires que les liaisons Python SQLite ne prennent pas en charge les séquences. Dans ce cas, vous voudrez peut-être
Généré par
la source
string.join les valeurs de la liste séparées par des virgules et utilisez l' opérateur format pour former une chaîne de requête.
(Merci, blair-conrad )
la source
%
formatage utilisé ici est simplement un formatage de chaîne Python.J'aime la réponse de Bobince:
Mais j'ai remarqué ceci:
Peut être remplacé par:
Je trouve cela plus direct mais moins intelligent et moins général. Ici, il
l
est nécessaire d'avoir une longueur (c'est-à-dire faire référence à un objet qui définit une__len__
méthode), ce qui ne devrait pas poser de problème. Mais l'espace réservé doit également être un caractère unique. Pour prendre en charge une utilisation d'espace réservé à plusieurs caractères:la source
Solution pour la réponse @umounted, car cela a rompu avec un tuple à un élément, puisque (1,) n'est pas un SQL valide .:
Autre solution pour la chaîne SQL:
la source
Cela devrait résoudre votre problème.
la source
Si vous utilisez PostgreSQL avec la bibliothèque Psycopg2, vous pouvez laisser son adaptation de tuple faire tout l'échappement et l'interpolation de chaîne pour vous, par exemple:
c'est-à-dire assurez-vous simplement que vous passez le
IN
paramètre en tant quetuple
. si c'est un,list
vous pouvez utiliser la= ANY
syntaxe du tableau :notez que ces deux éléments seront transformés en le même plan de requête, vous devez donc simplement utiliser celui qui est le plus facile. Par exemple, si votre liste vient dans un tuple, utilisez la première, si elle est stockée dans une liste, utilisez la seconde.
la source
Par exemple, si vous voulez la requête SQL:
Qu'en est-il de:
la source
une solution plus simple:
la source
La
:var
notation semble plus simple. (Python 3.7)la source
Cela utilise la substitution de paramètres et prend en charge le cas de liste à valeur unique:
la source