Mam listę Pythona, powiedz l
l = [1,5,8]
Chcę napisać zapytanie sql, aby uzyskać dane dla, powiedzmy, wszystkich elementów listy
select name from students where id = |IN THE LIST l|
Jak to osiągnąć?
Odpowiedzi do tej pory umieszczały wartości w postaci zwykłego ciągu SQL. Jest to absolutnie w porządku w przypadku liczb całkowitych, ale jeśli chcemy to zrobić dla łańcuchów, pojawia się problem ze ucieczką.
Oto wariant używający sparametryzowanego zapytania, który zadziała w obu przypadkach:
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))
byłby nieco krótszy, a nadal czytelny([placeholder]*len(l))
w ogólnym przypadku musi to być, ponieważ symbol zastępczy może mieć wiele znaków.cursor.execute(f'SELECT name FROM students WHERE id IN ({','.join('?' for _ in l)})', l)
. @bobince, powinieneś również zauważyć w swoim rozwiązaniu, że używanie?
jest bezpiecznym sposobem na uniknięcie iniekcji SQL. Jest tutaj wiele odpowiedzi, które są podatne na ataki, w zasadzie te, które łączą ciągi znaków w Pythonie.Najłatwiej jest obrócić listę na
tuple
pierwsząźródło
Nie komplikuj tego, rozwiązanie tego jest proste.
Mam nadzieję, że to pomogło !!!
źródło
l
zawiera tylko jeden element, skończyszid IN (1,)
. Co jest błędem składniowym.sqlite3
. Z jaką biblioteką to przetestowałeś?Żądany SQL to
Jeśli chcesz zbudować to z Pythona, możesz użyć
Funkcja map przekształci listę w listę ciągów, które można skleić przecinkami przy użyciu metody str.join .
Alternatywnie:
jeśli wolisz wyrażenia generatora od funkcji mapy.
UPDATE: S. Lott wspomina w komentarzach, że powiązania Python SQLite nie obsługują sekwencji. W takim przypadku możesz chcieć
Wygenerowane przez
źródło
ciąg. dołącz wartości listy oddzielone przecinkami i użyj operatora formatu, aby utworzyć ciąg zapytania.
(Dzięki, blair-conrad )
źródło
%
Byt używany tutaj jest po prostu Python ciąg formatowania.Podoba mi się odpowiedź Bobince'a:
Ale zauważyłem to:
Można wymienić na:
Uważam, że jest to bardziej bezpośrednie, jeśli mniej sprytne i mniej ogólne. Tutaj
l
wymagana jest długość (tj. Odwołanie się do obiektu, który definiuje__len__
metodę), co nie powinno stanowić problemu. Ale symbol zastępczy musi również być pojedynczym znakiem. Aby obsługiwać wieloznakowy symbol zastępczy:źródło
Rozwiązanie dla odpowiedzi @umounted, ponieważ zostało przerwane z jednoelementową krotką, ponieważ (1,) nie jest poprawnym kodem SQL .:
Inne rozwiązanie dla ciągu sql:
źródło
To powinno rozwiązać twój problem.
źródło
Jeśli używasz PostgreSQL z biblioteką Psycopg2, możesz pozwolić jej adaptacji krotek na wykonanie wszystkich znaków ucieczki i interpolacji ciągów, np .:
czyli po prostu upewnij się, że przekazujesz
IN
parametr jako pliktuple
. jeśli to alist
, możesz użyć= ANY
składni tablicy :zwróć uwagę, że oba zostaną przekształcone w ten sam plan zapytań, więc powinieneś po prostu użyć tego, który jest łatwiejszy. np. jeśli twoja lista znajduje się w krotce, użyj pierwszej, jeśli jest przechowywana w liście, użyj drugiej.
źródło
Na przykład, jeśli chcesz, aby zapytanie sql:
Co powiesz na:
źródło
prostsze rozwiązanie:
źródło
:var
Zapis wydaje się prostsze. (Python 3.7)źródło
To używa podstawiania parametrów i zajmuje się przypadkiem listy pojedynczej wartości:
źródło