У меня есть массив значений в Python, который мне нужно использовать в предложении IN в запросе SQL. Массив не имеет фиксированного размера. В настоящее время я использую простую замену строк, но я бы предпочел использовать именованные переменные связывания, чтобы избежать атак с использованием sql-инъекций и чтобы я мог ссылаться на одну и ту же переменную в нескольких местах SQL-запроса:
Мой текущий код (упрощенная выдержка):
Код: Выделить всё
accts = ['A123', 'B456', 'C789']
acct_list = ','.join(["'%s'" % a for a in accts])
cursor.execute('''
SELECT A,B,C FROM SOME_TABLE WHERE ACCT_CODE IN ({alist})
UNION SELECT A,B,C FROM OTHER_TABLE WHERE ACCT_CODE IN ({alist})
'''.format(alist=acct_list))
В идеале мне бы хотелось сделать что-то подобное, но я знаю, что это не так просто:
Код: Выделить всё
accts = ['A123', 'B456', 'C789']
cursor.execute('''
SELECT A,B,C FROM SOME_TABLE WHERE ACCT_CODE IN (:alist)
UNION SELECT A,B,C FROM OTHER_TABLE WHERE ACCT_CODE IN (:alist)
''', alist=accts)
Единственное решение, о котором я до сих пор думал, это следующее, но оно далеко не идеально, особенно когда у меня есть другие переменные SQL помимо этого списка:
Код: Выделить всё
accts = ['A123', 'B456', 'C789']
vars = ['acct%d' % int(x+1) for x,a in enumerate(accts)]
vlist = ','.join([':%s' % v for v in vars])
parms = dict(zip(vars, accts))
sql = '''
SELECT A,B,C FROM SOME_TABLE WHERE ACCT_CODE IN ({vlist})
UNION SELECT A,B,C FROM OTHER_TABLE WHERE ACCT_CODE IN ({vlist})
'''.format(vlist=vlist)
cursor.execute(sql, parms)
Последний блок кода выше позволит мне делать все, что мне нужно, включая добавление дополнительных параметров в словарь запроса и параметров, но такое ощущение, будто я хожу по сараю сделать что-то, что не должно быть так сложно. Прежде чем я изменил весь свой код для использования этого решения, я подумал, что посмотрю, знает ли кто-нибудь здесь более «правильный» способ сделать это.
Подробнее здесь:
https://stackoverflow.com/questions/251 ... -in-clause