Ich habe eine Python-Liste, sag ich
l = [1,5,8]
Ich möchte eine SQL-Abfrage schreiben, um beispielsweise die Daten für alle Elemente der Liste abzurufen
select name from students where id = |IN THE LIST l|
Wie schaffe ich das?
Ich habe eine Python-Liste, sag ich
l = [1,5,8]
Ich möchte eine SQL-Abfrage schreiben, um beispielsweise die Daten für alle Elemente der Liste abzurufen
select name from students where id = |IN THE LIST l|
Wie schaffe ich das?
Antworten:
Bisher wurden die Werte in eine einfache SQL-Zeichenfolge umgewandelt. Das ist absolut in Ordnung für ganze Zahlen, aber wenn wir es für Strings tun wollten, bekommen wir das Escape-Problem.
Hier ist eine Variante mit einer parametrisierten Abfrage, die für beide funktioniert:
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)
([placeholder]*len(l))im allgemeinen Fall sein, da der Platzhalter aus mehreren Zeichen bestehen kann.
cursor.execute(f'SELECT name FROM students WHERE id IN ({','.join('?' for _ in l)})', l) . @bobince, Sie sollten in Ihrer Lösung auch bemerken, dass die Verwendung ?der sichere Weg ist, um SQL-Injection zu vermeiden. Hier gibt es viele Antworten, die anfällig sind, im Grunde alle, die Zeichenfolgen in Python verketten.
Am einfachsten ist es, die Liste an die tupleerste Stelle zu setzen
t = tuple(l)
query = "select name from studens where id IN {}".format(t)
Komplizieren Sie es nicht, die Lösung hierfür ist einfach.
l = [1,5,8]
l = tuple(l)
params = {'l': l}
cursor.execute('SELECT * FROM table where id in %(l)s',params)
Ich hoffe das hat geholfen !!!
lnur ein Element enthalten ist id IN (1,). Welches ist ein Syntaxfehler.
sqlite3. Mit welcher Bibliothek haben Sie das getestet?
Das gewünschte SQL ist
select name from studens where id in (1, 5, 8)
Wenn Sie dies aus der Python konstruieren möchten, können Sie verwenden
l = [1, 5, 8]
sql_query = 'select name from studens where id in (' + ','.join(map(str, l)) + ')'
Die Map- Funktion wandelt die Liste in eine Liste von Zeichenfolgen um, die mit der Methode str.join durch Kommas zusammengeklebt werden können .
Alternative:
l = [1, 5, 8]
sql_query = 'select name from studens where id in (' + ','.join((str(n) for n in l)) + ')'
Wenn Sie Generatorausdrücke der Kartenfunktion vorziehen .
AKTUALISIEREN: S. Lott erwähnt in den Kommentaren, dass die Python SQLite-Bindungen keine Sequenzen unterstützen. In diesem Fall möchten Sie vielleicht
select name from studens where id = 1 or id = 5 or id = 8
Erstellt von
sql_query = 'select name from studens where ' + ' or '.join(('id = ' + str(n) for n in l))
String.Join die Liste Wert durch Kommata getrennt, und verwenden Sie das Format Operator eine Abfrage - Zeichenfolge zu bilden.
myquery = "select name from studens where id in (%s)" % ",".join(map(str,mylist))
(Danke, Blair-Conrad )
%Wesen verwendet hier ist einfach nur Python - String formatiert wird .
Ich mag die Antwort von Bobince:
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)
Aber mir ist das aufgefallen:
placeholders= ', '.join(placeholder for unused in l)
Kann ersetzt werden durch:
placeholders= ', '.join(placeholder*len(l))
Ich finde das direkter, wenn auch weniger klug und weniger allgemein. Hier lmuss eine Länge vorhanden sein (dh auf ein Objekt verweisen, das eine __len__Methode definiert ), was kein Problem sein sollte. Platzhalter müssen aber auch ein einzelnes Zeichen sein. So unterstützen Sie einen Platzhalter mit mehreren Zeichen:
placeholders= ', '.join([placeholder]*len(l))
Lösung für @umounted Antwort, da dies mit einem Ein-Element-Tupel brach, da (1,) kein gültiges SQL ist:
>>> random_ids = [1234,123,54,56,57,58,78,91]
>>> cursor.execute("create table test (id)")
>>> for item in random_ids:
cursor.execute("insert into test values (%d)" % item)
>>> sublist = [56,57,58]
>>> cursor.execute("select id from test where id in %s" % str(tuple(sublist)).replace(',)',')'))
>>> a = cursor.fetchall()
>>> a
[(56,), (57,), (58,)]
Andere Lösung für SQL-Zeichenfolge:
cursor.execute("select id from test where id in (%s)" % ('"'+'", "'.join(l)+'"'))
placeholders= ', '.join("'{"+str(i)+"}'" for i in range(len(l)))
query="select name from students where id (%s)"%placeholders
query=query.format(*l)
cursor.execute(query)
Dies sollte Ihr Problem lösen.
Wenn Sie PostgreSQL mit der psycopg2 Bibliothek verwenden können Sie sein lassen Tupel Anpassung für Sie alle entkommen und String - Interpolation tun, zum Beispiel:
ids = [1,2,3]
cur.execute(
"SELECT * FROM foo WHERE id IN %s",
[tuple(ids)])
Stellen Sie einfach sicher, dass Sie den INParameter als übergeben tuple. Wenn es ein ist list, können Sie die = ANYArray-Syntax verwenden :
cur.execute(
"SELECT * FROM foo WHERE id = ANY (%s)",
[list(ids)])
Beachten Sie, dass beide in denselben Abfrageplan umgewandelt werden, sodass Sie nur den einfacheren verwenden sollten. Wenn Ihre Liste beispielsweise in einem Tupel vorliegt, verwenden Sie das erstere. Wenn sie in einer Liste gespeichert sind, verwenden Sie das letztere.
eine einfachere Lösung:
lst = [1,2,3,a,b,c]
query = f"""SELECT * FROM table WHERE IN {str(lst)[1:-1}"""
l = [1] # or [1,2,3]
query = "SELECT * FROM table WHERE id IN :l"
params = {'l' : tuple(l)}
cursor.execute(query, params)
Die :varNotation scheint einfacher. (Python 3.7)
Dies verwendet die Parametersubstitution und kümmert sich um den Fall der Einzelwertliste:
l = [1,5,8]
get_operator = lambda x: '=' if len(x) == 1 else 'IN'
get_value = lambda x: int(x[0]) if len(x) == 1 else x
query = 'SELECT * FROM table where id ' + get_operator(l) + ' %s'
cursor.execute(query, (get_value(l),))
','.join(placeholder * len(l))wäre etwas kürzer während noch lesbar imho