ฉันมีรายการหลามพูด l
l = [1,5,8]
ฉันต้องการเขียนแบบสอบถาม sql เพื่อรับข้อมูลสำหรับองค์ประกอบทั้งหมดของรายการพูด
select name from students where id = |IN THE LIST l|
ฉันจะทำสิ่งนี้ให้สำเร็จได้อย่างไร?
ฉันมีรายการหลามพูด l
l = [1,5,8]
ฉันต้องการเขียนแบบสอบถาม sql เพื่อรับข้อมูลสำหรับองค์ประกอบทั้งหมดของรายการพูด
select name from students where id = |IN THE LIST l|
ฉันจะทำสิ่งนี้ให้สำเร็จได้อย่างไร?
คำตอบ:
คำตอบที่ผ่านมาได้ทำการเทมเพลตค่าเป็นสตริง SQL ธรรมดา เป็นเรื่องที่ดีสำหรับจำนวนเต็ม แต่ถ้าเราต้องการทำสำหรับสตริงเราจะได้รับปัญหาการหลีกเลี่ยง
นี่คือตัวแปรที่ใช้แบบสอบถามที่กำหนดพารามิเตอร์ซึ่งจะใช้ได้กับทั้งสองอย่าง:
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))
กรณีทั่วไปเนื่องจากตัวยึดอาจมีหลายอักขระ
cursor.execute(f'SELECT name FROM students WHERE id IN ({','.join('?' for _ in l)})', l)
3.6 @bobince คุณควรตั้งข้อสังเกตในโซลูชันของคุณว่าการใช้?
เป็นวิธีที่ปลอดภัยในการหลีกเลี่ยงการฉีด SQL มีคำตอบมากมายที่นี่ซึ่งมีช่องโหว่โดยพื้นฐานแล้วคำตอบใด ๆ ที่เชื่อมต่อสตริงใน python
วิธีที่ง่ายที่สุดคือเปลี่ยนรายการเป็นtuple
อันดับแรก
t = tuple(l)
query = "select name from studens where id IN {}".format(t)
อย่าซับซ้อนวิธีแก้ปัญหานี้ง่ายมาก
l = [1,5,8]
l = tuple(l)
params = {'l': l}
cursor.execute('SELECT * FROM table where id in %(l)s',params)
หวังว่านี่จะช่วยได้ !!!
l
id IN (1,)
ซึ่งเป็นข้อผิดพลาดทางไวยากรณ์
sqlite3
นี้ไม่ได้ทำงานให้ฉันด้วย คุณทดสอบสิ่งนี้กับห้องสมุดใด
SQL ที่คุณต้องการคือ
select name from studens where id in (1, 5, 8)
หากคุณต้องการสร้างสิ่งนี้จาก python คุณสามารถใช้
l = [1, 5, 8]
sql_query = 'select name from studens where id in (' + ','.join(map(str, l)) + ')'
แผนที่ฟังก์ชั่นจะเปลี่ยนรายชื่อลงในรายการของสตริงที่สามารถติดกาวเข้าด้วยกันโดยใช้เครื่องหมายจุลภาคที่str.joinวิธี
อีกวิธีหนึ่งคือ:
l = [1, 5, 8]
sql_query = 'select name from studens where id in (' + ','.join((str(n) for n in l)) + ')'
หากคุณต้องการนิพจน์ตัวสร้างกับฟังก์ชันแผนที่
UPDATE: S. Lottกล่าวในความคิดเห็นว่าการเชื่อมโยง Python SQLite ไม่รองรับลำดับ ในกรณีนี้คุณอาจต้องการ
select name from studens where id = 1 or id = 5 or id = 8
ที่สร้างขึ้นโดย
sql_query = 'select name from studens where ' + ' or '.join(('id = ' + str(n) for n in l))
สตริงเข้าร่วมค่ารายการที่คั่นด้วยเครื่องหมายจุลภาคและใช้ตัวดำเนินการรูปแบบเพื่อสร้างสตริงแบบสอบถาม
myquery = "select name from studens where id in (%s)" % ",".join(map(str,mylist))
(ขอบคุณแบลร์คอนราด )
%
ถูกนำมาใช้ที่นี่เป็นเพียงธรรมดาสตริงหลามการจัดรูปแบบ
ฉันชอบคำตอบของ 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)
แต่ฉันสังเกตเห็นสิ่งนี้:
placeholders= ', '.join(placeholder for unused in l)
สามารถแทนที่ด้วย:
placeholders= ', '.join(placeholder*len(l))
ฉันพบว่าสิ่งนี้ตรงกว่าถ้าฉลาดน้อยกว่าและไม่ค่อยมีคนทั่วไป ต่อไปl
นี้จำเป็นต้องมีความยาว (เช่นอ้างถึงวัตถุที่กำหนด__len__
วิธีการ) ซึ่งไม่น่าจะเป็นปัญหา แต่ตัวยึดจะต้องเป็นอักขระเดี่ยวด้วย เพื่อรองรับการใช้ตัวยึดแบบหลายอักขระ:
placeholders= ', '.join([placeholder]*len(l))
วิธีแก้ปัญหาสำหรับคำตอบ @umounted เพราะมันแตกด้วยทูเปิลองค์ประกอบเดียวเนื่องจาก (1) ไม่ใช่ SQL ที่ถูกต้อง
>>> 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:
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)
วิธีนี้จะช่วยแก้ปัญหาของคุณได้
หากคุณใช้ PostgreSQL กับไลบรารี Psycopg2 คุณสามารถปล่อยให้การปรับตัวแบบทูเพิลทำการแก้ไขค่า Escape และการแก้ไขสตริงให้คุณได้เช่น:
ids = [1,2,3]
cur.execute(
"SELECT * FROM foo WHERE id IN %s",
[tuple(ids)])
กล่าวคือตรวจสอบให้แน่ใจว่าคุณกำลังส่งIN
พารามิเตอร์เป็นไฟล์tuple
. ถ้าเป็นlist
คุณสามารถใช้= ANY
ไวยากรณ์อาร์เรย์ :
cur.execute(
"SELECT * FROM foo WHERE id = ANY (%s)",
[list(ids)])
โปรดทราบว่าทั้งสองอย่างนี้จะกลายเป็นแผนการสืบค้นเดียวกันดังนั้นคุณควรใช้สิ่งที่ง่ายกว่า เช่นถ้ารายการของคุณเป็นทูเพิลให้ใช้แบบเดิมหากเก็บไว้ในรายการให้ใช้รายการหลัง
ตัวอย่างเช่นหากคุณต้องการเคียวรี sql:
select name from studens where id in (1, 5, 8)
สิ่งที่เกี่ยวกับ:
my_list = [1, 5, 8]
cur.execute("select name from studens where id in %s" % repr(my_list).replace('[','(').replace(']',')') )
วิธีแก้ปัญหาที่ง่ายกว่า:
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)
:var
โน้ตดูเหมือนง่าย (Python 3.7)
สิ่งนี้ใช้การทดแทนพารามิเตอร์และดูแลกรณีรายการค่าเดียว:
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))
จะสั้นลงเล็กน้อยในขณะที่ยังอ่านได้ imho