Bir piton listem var, diyelim ki
l = [1,5,8]
Listenin tüm öğelerinin verilerini almak için bir sql sorgusu yazmak istiyorum, diyelim ki
select name from students where id = |IN THE LIST l|
Bunu nasıl başarırım?
Bir piton listem var, diyelim ki
l = [1,5,8]
Listenin tüm öğelerinin verilerini almak için bir sql sorgusu yazmak istiyorum, diyelim ki
select name from students where id = |IN THE LIST l|
Bunu nasıl başarırım?
Yanıtlar:
Şimdiye kadarki cevaplar, değerleri düz bir SQL dizgisine dönüştürüyordu. Bu tamsayılar için kesinlikle sorun değil, ancak bunu dizeler için yapmak istersek, kaçış sorununu alırız.
Her ikisi için de işe yarayacak parametreli sorgu kullanan bir varyant:
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))yer tutucu birden çok karakter olabileceğinden genel durumda olması gerekir.
cursor.execute(f'SELECT name FROM students WHERE id IN ({','.join('?' for _ in l)})', l). @bobince, çözümünüzde kullanmanın ?SQL enjeksiyonundan kaçınmak açısından güvenli bir yol olduğunu da belirtmelisiniz . Burada savunmasız pek çok cevap var, temelde python'da dizeleri birleştiren cevaplar.
En kolay yol listeyi tupleilk sıraya çevirmektir
t = tuple(l)
query = "select name from studens where id IN {}".format(t)
Karmaşıklaştırmayın, Bunun çözümü basit.
l = [1,5,8]
l = tuple(l)
params = {'l': l}
cursor.execute('SELECT * FROM table where id in %(l)s',params)
Umarım bu yardımcı olmuştur !!!
lyalnızca bir öğe içeriyorsa işe yaramaz , sonunda elde edersiniz id IN (1,). Bu bir sözdizimi hatasıdır.
sqlite3. Bunu hangi kütüphaneye karşı test ettiniz?
İstediğiniz SQL
select name from studens where id in (1, 5, 8)
Bunu python'dan inşa etmek istiyorsanız,
l = [1, 5, 8]
sql_query = 'select name from studens where id in (' + ','.join(map(str, l)) + ')'
Harita işlevi kullanarak virgülle yapıştırılmış olabilir dizeleri bir liste halinde listeyi değiştirecek str.join yöntemi.
Alternatif:
l = [1, 5, 8]
sql_query = 'select name from studens where id in (' + ','.join((str(n) for n in l)) + ')'
harita işlevine jeneratör ifadelerini tercih ederseniz .
GÜNCELLEME: S. Lott yorumlarda Python SQLite bağlamalarının dizileri desteklemediğinden bahsediyor. Bu durumda isteyebilirsin
select name from studens where id = 1 or id = 5 or id = 8
Oluşturan
sql_query = 'select name from studens where ' + ' or '.join(('id = ' + str(n) for n in l))
String.Join virgülle ayrılmış liste değerlerini ve kullanım biçimi operatörü sorgu dizisi oluşturulur.
myquery = "select name from studens where id in (%s)" % ",".join(map(str,mylist))
(Teşekkürler blair-conrad )
%Burada kullanılan varlık biçimlendirme sadece düz Python dizedir.
Bobince'nin cevabını beğendim:
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)
Ama şunu fark ettim:
placeholders= ', '.join(placeholder for unused in l)
Şununla değiştirilebilir:
placeholders= ', '.join(placeholder*len(l))
Daha az zeki ve daha az genel olsa da bunu daha dolaysız buluyorum. Burada lbir uzunluğa sahip olmak gerekir (yani bir __len__yöntemi tanımlayan bir nesneye atıfta bulunun ), ki bu bir problem olmamalıdır. Ancak yer tutucunun da tek bir karakter olması gerekir. Çok karakterli bir yer tutucuyu desteklemek için:
placeholders= ', '.join([placeholder]*len(l))
@Umounted cevabı için çözüm, çünkü bu tek öğeli bir demetle bozuldu, çünkü (1,) geçerli SQL değil:
>>> 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,)]
Sql dizesi için diğer çözüm:
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)
Bu probleminizi çözmeli.
PostgreSQL'i Psycopg2 kitaplığı ile kullanıyorsanız, tuple uyarlamasının sizin için tüm kaçış ve dize enterpolasyonunu yapmasına izin verebilirsiniz , örneğin:
ids = [1,2,3]
cur.execute(
"SELECT * FROM foo WHERE id IN %s",
[tuple(ids)])
yani, INparametreyi bir tuple. eğer bir listise = ANYdizi sözdizimini kullanabilirsiniz :
cur.execute(
"SELECT * FROM foo WHERE id = ANY (%s)",
[list(ids)])
bunların her ikisinin de aynı sorgu planına dönüşeceğini unutmayın, bu nedenle hangisi daha kolaysa onu kullanmanız gerekir. Örneğin, listeniz bir demet halinde gelirse, ilkini, bir listede saklanıyorlarsa ikincisini kullanın.
daha basit bir çözüm:
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)
:varNotasyonu daha basit görünüyor. (Python 3.7)
Bu, parametre değiştirmeyi kullanır ve tek değer listesi durumuyla ilgilenir:
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))hala okunabilir iken biraz daha kısa olurdu