প্যারামিটার হিসাবে বর্গ কোয়েরিতে অজগর তালিকা list


124

আমার একটি অজগর তালিকা আছে, বলুন

l = [1,5,8]

আমি তালিকার সমস্ত উপাদানগুলির ডেটা পেতে একটি বর্গ কোয়েরি লিখতে চাই, বলুন

select name from students where id = |IN THE LIST l|

আমি কীভাবে এটি সম্পাদন করব?

উত্তর:


111

উত্তরগুলি এখনও অবধি মানকে একটি সরল এসকিউএল স্ট্রিংয়ে টেম্প্লেট করছে। এটি পূর্ণসংখ্যার জন্য একেবারে ঠিক আছে, তবে আমরা যদি স্ট্রিংয়ের জন্য এটি করতে চাই তবে আমরা পালানোর সমস্যাটি পাই।

এখানে প্যারামিটারাইজড ক্যোয়ারী ব্যবহার করে একটি বৈকল্পিক যা উভয়ের জন্যই কার্যকর হবে:

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)

11
','.join(placeholder * len(l))
ইমো

7
@ থিফমাস্টার: হ্যাঁ, ([placeholder]*len(l))সাধারণ ক্ষেত্রে হতে হবে কারণ স্থানধারক একাধিক অক্ষর থাকতে পারে।
ববিনস

1
@ ববিন্স আমার ক্ষেত্রে আমি একটি = 'জন' এবং বি = 'তুষার' একটি ভেরিয়েবল নির্ধারণ করেছি এবং এটি পেয়েছি = ['a, b'] নামের একটি টুপলে সংরক্ষণ করেছি এবং একই প্রশ্নটি সম্পাদন করেছি। এটি করার ফলে আমি ভুলটি পেয়েছি অর্থাৎ টাইপ ত্রুটি: স্ট্রিং ফর্ম্যাটিংয়ের সময় সমস্ত যুক্তি রূপান্তরিত হয় না। আমার কীভাবে এটি সমাধান করার কথা
টেকজোলা

2
আপনি এই কাজটি ডিবাপি ছেড়ে না গিয়ে কেন "হাত ধরে" যোগ দিতে চান?
মূলটি হ'ল

5
এই উত্তরটির উপর ভিত্তি করে পাইথন 3.6 এর জন্য একটি একক লাইন সমাধান রয়েছে cursor.execute(f'SELECT name FROM students WHERE id IN ({','.join('?' for _ in l)})', l)। @ বিবিস, আপনার সমাধানে আপনার মন্তব্য করা উচিত যে ?এসকিউএল ইঞ্জেকশন এড়ানোর ক্ষেত্রে ব্যবহার করা নিরাপদ উপায়। এখানে প্রচুর উত্তর রয়েছে যা অরক্ষিত, মূলত যে কোনও অজগরটিতে স্ট্রিংগুলি যুক্ত করে।
টোটো_টিকো

59

সবচেয়ে সহজ উপায় হ'ল tupleপ্রথমে তালিকাটি চালু করা

t = tuple(l)
query = "select name from studens where id IN {}".format(t)

1
এটি আসলে সঠিক উত্তর। কেন এড়িয়ে গেল তা নিশ্চিত নই। প্রথমে আপনি তালিকাটি সেট আপ করুন, তারপরে টিপল ব্যবহার করুন, তারপরে টিপলটিকে কোয়েরিতে পাস করুন। সাবাশ.
এমডউইন

11
@ রেঞ্জারস্টেমের বক্তব্য অনুসারে, যদি কেবলমাত্র একটি উপাদান থাকে তবে এটি কাজ করে না, আপনি আইডি আইএন (1,) দিয়ে শেষ করবেন। যা একটি সিনট্যাক্স ত্রুটি।
ডাবলডাউন

1
@Boris আপনি নিশ্চয়তা দিতে পারে না আপনার ইনপুট সবসময় একটি তালিকা, আপনি এই এক মাছ ধরার নৌকা অনুরূপ কিছু করতে পারেন stackoverflow.com/questions/38821586/... তোমার প্রশ্নের যেই সব যুক্তি ক্ষণস্থায়ী আগে
আমির Imani

10
এটি, গৃহীত উত্তর ব্যতীত এখানে বেশিরভাগ উত্তরের মতো, এসকিউএল ইঞ্জেকশনের পক্ষে ঝুঁকিপূর্ণ এবং এটি ব্যবহার করা উচিত নয়।
বেকন বিট 21

2
@ বাকনবিটস ফেয়ার সতর্কতা, তবে কিছু অ্যাপ্লিকেশনের ক্ষেত্রে যেখানে এসকিউএল ইঞ্জেকশন কোনও সমস্যা নয় (উদাহরণস্বরূপ, যেখানে আমি একমাত্র ব্যবহারকারী সেখানে একটি ডাটাবেস বিশ্লেষণ), এটি করবে।
আয়রিন

26

এটিকে জটিল করবেন না, এর সমাধান খুব সহজ is

l = [1,5,8]

l = tuple(l)

params = {'l': l}

cursor.execute('SELECT * FROM table where id in %(l)s',params)

এখানে চিত্র বর্ণনা লিখুন

আমি আশা করি এটি সাহায্য করেছে !!!


10
যদি lকেবল একটি উপাদান থাকে তবে এটি কাজ করে না , আপনি শেষ করবেন id IN (1,)। যা একটি সিনট্যাক্স ত্রুটি।
পুনরুত্থান

3
যদি কেবলমাত্র 1 টি উপাদান থাকে তবে নিশ্চিত হয়ে নিন যে এটি একটি টিপল এবং এটি কাজ করবে। এই সমাধানটি আমার মতে গৃহীত সমস্যার চেয়ে পরিষ্কার।
আলেসান্দ্রো ডেন্টেলা

2
তবে টিপল খালি থাকলে এটি এখনও কাজ করবে না, সুতরাং কোয়েরি কার্যকর করার আগে অতিরিক্ত চেক থাকতে হবে।
22

2
এটি আমার পক্ষে কাজ করে না sqlite3। আপনি কোন লাইব্রেরির বিরুদ্ধে এটি পরীক্ষা করেছেন?
নিক চ্যামাস

1
ভাল সমাধান তবে @renstrm এবং Никита-টিউপলের যখন একটি একক উপাদান রয়েছে বা কোনও উপাদান নেই তখন অতিরিক্ত চেকের প্রয়োজন about
আনিস সানা

23

আপনি যে এসকিউএল চান তা হ'ল

select name from studens where id in (1, 5, 8)

আপনি যদি পাইথন থেকে এটি নির্মাণ করতে চান তবে আপনি ব্যবহার করতে পারেন

l = [1, 5, 8]
sql_query = 'select name from studens where id in (' + ','.join(map(str, l)) + ')'

মানচিত্র ফাংশন স্ট্রিং একটি তালিকা যে ব্যবহার কমা দ্বারা একসঙ্গে glued করা যাবে মধ্যে তালিকা রূপান্তরিত হবে str.join পদ্ধতি।

বিকল্পভাবে:

l = [1, 5, 8]
sql_query = 'select name from studens where id in (' + ','.join((str(n) for n in l)) + ')'

আপনি যদি জেনারেটর এক্সপ্রেশন পছন্দ করেন মানচিত্রের কার্যক্রমে ।

আপডেট: এস লট মন্তব্যগুলিতে উল্লেখ করেছেন যে পাইথন এসকিউএলাইট বাইন্ডিংগুলি ক্রমগুলি সমর্থন করে না। সেক্ষেত্রে আপনি চাইবেন

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))

2
:-( পাইথন
এসকিউএলাইট

উহু? আমি বুঝতে পারিনি। তারপরে আবার, আমি বুঝতে পারি না যে আমরা একটি এসকিউএল বাইন্ডিং সমাধানের জন্য যাচ্ছি।
ব্লেয়ার কনরাড

দুঃখিত, এসকিউএলাইট প্রস্তাব বা তাত্পর্যপূর্ণ নয় - কেবল দুঃখের বিষয় যে তালিকার জন্য বাইন্ডিংগুলি সেখানে কাজ করে না।
এস .লট

11

স্ট্রিং.কোমাস দ্বারা বিভক্ত তালিকার মানগুলিতে যোগদান করুন এবং একটি ক্যোরি স্ট্রিং তৈরি করতে ফর্ম্যাট অপারেটরটি ব্যবহার করুন ।

myquery = "select name from studens where id in (%s)" % ",".join(map(str,mylist))

(ধন্যবাদ, ব্লেয়ার-কনরাড )


2
যেহেতু এই পদ্ধতিটি ডাটাবেস প্যারামিটার বিকল্প ব্যবহার করে না, এটি আপনাকে এসকিউএল ইঞ্জেকশন আক্রমণগুলিতে প্রকাশ করে। এখানে %ব্যবহৃত হচ্ছে কেবল সরল পাইথন স্ট্রিং ফর্ম্যাটিং।
নিক চ্যামাস

8

আমি বোবিন্সের উত্তরটি পছন্দ করি:

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))

2

@ পরিমাণযুক্ত উত্তরের জন্য সমাধান, কারণ এটি এক-মৌলিক মূল্যের সাথে ভেঙে গেছে, যেহেতু (1,) বৈধ এসকিউএল নয়:

>>> 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,)]

স্কয়ার স্ট্রিংয়ের অন্যান্য সমাধান:

cursor.execute("select id from test where id in (%s)" % ('"'+'", "'.join(l)+'"'))

5
এসকিএল ইঞ্জেকশনের কারণে এটি আরও ভাল সমাধান নয়।
অনুরাগ

2
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)

এটা আপনার সমস্যা সমাধান করবে.


2

আপনি যদি সাইকোপজি 2 লাইব্রেরির সাথে পোস্টগ্রিজ এসকিউএল ব্যবহার করে থাকেন তবে আপনি এর টিপল অ্যাডাপশনটি আপনার জন্য সমস্ত প্রস্থান এবং স্ট্রিং ইন্টারপোলেশন করতে দিতে পারেন, যেমন:

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)])

মনে রাখবেন যে এই দুটিই একই ক্যোয়ারী পরিকল্পনায় রূপান্তরিত হবে তাই আপনার মধ্যে যে কোনওটি সহজ use উদাহরণস্বরূপ, যদি আপনার তালিকাটি একটি টিপলে আসে তবে প্রাক্তনটিকে ব্যবহার করুন, যদি তারা একটি তালিকায় সঞ্চিত থাকে তবে পরবর্তীটি ব্যবহার করুন।


1

উদাহরণস্বরূপ, আপনি যদি এসকিএল কোয়েরি চান:

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(']',')') )


1
l = [1] # or [1,2,3]

query = "SELECT * FROM table WHERE id IN :l"
params = {'l' : tuple(l)}
cursor.execute(query, params)

:varস্বরলিপি সহজ বলে মনে হয়। (পাইথন ৩.7)


0

এটি প্যারামিটার বিকল্প ব্যবহার করে এবং একক মান তালিকার কেস যত্ন করে:

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),))
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.