programing tip

파이썬 MySQLDB IN 절에서 사용하기 위해 목록을 파열

itbloger 2020. 10. 27. 07:54
반응형

파이썬 MySQLDB IN 절에서 사용하기 위해 목록을 파열


목록을 문자열에 매핑하는 방법을 알고 있습니다.

foostring = ",".join( map(str, list_of_ids) )

그리고 다음을 사용하여 해당 문자열을 IN 절로 가져올 수 있음을 알고 있습니다.

cursor.execute("DELETE FROM foo.bar WHERE baz IN ('%s')" % (foostring))

내가 필요한 것은 MySQLDB를 사용하여 동일한 작업을 안전하게 수행하는 것입니다 (SQL 주입 방지). 위의 예에서는 foostring이 실행을위한 인자로 전달되지 않기 때문에 취약합니다. 또한 mysql 라이브러리 외부에서 인용하고 탈출해야합니다.

( 관련 SO 질문 이 있지만 여기에 나열된 답변은 MySQLDB에서 작동하지 않거나 SQL 주입에 취약합니다.)


list_of_ids직접 사용 :

format_strings = ','.join(['%s'] * len(list_of_ids))
cursor.execute("DELETE FROM foo.bar WHERE baz IN (%s)" % format_strings,
                tuple(list_of_ids))

그렇게하면 자신을 인용 할 필요가없고 모든 종류의 SQL 주입을 피할 수 있습니다.

데이터 ( list_of_ids)는 매개 변수 (쿼리 텍스트가 아님)로 mysql의 드라이버로 직접 이동하므로 주입이 없습니다. 문자열에 원하는 문자를 남겨 둘 수 있으며 문자를 제거하거나 인용 할 필요가 없습니다.


당신이 사용하는 경우 Django 2.0 or 2.1Python 3.6, 이것은 올바른 방법입니다 :

from django.db import connection
RESULT_COLS = ['col1', 'col2', 'col3']
RESULT_COLS_STR = ', '.join(['a.'+'`'+i+'`' for i in RESULT_COLS])
QUERY_INDEX = RESULT_COLS[0]

TABLE_NAME = 'test'
search_value = ['ab', 'cd', 'ef']  # <-- a list
query = (
    f'SELECT DISTINCT {RESULT_COLS_STR} FROM {TABLE_NAME} a '
    f'WHERE a.`{RESULT_COLS[0]}` IN %s '
    f'ORDER BY a.`{RESULT_COLS[0]}`;'
)  # <- 'SELECT DISTINCT a.`col1`, a.`col2`, a.`col3` FROM test a WHERE a.`col1` IN %s ORDER BY a.`col1`;'
with connection.cursor() as cursor:
    cursor.execute(query, params=[search_value])  # params is a list with a list as its element

참조 : https://stackoverflow.com/a/23891759/2803344 https://docs.djangoproject.com/en/2.1/topics/db/sql/#passing-parameters-into-raw


무통 MySQLdb execute('...WHERE name1 = %s AND name2 IN (%s)', value1, values2)

def execute(sql, *values):

    assert sql.count('%s') == len(values), (sql, values)
    placeholders = []
    new_values = []
    for value in values:
        if isinstance(value, (list, tuple)):
            placeholders.append(', '.join(['%s'] * len(value)))
            new_values.extend(value)
        else:
            placeholders.append('%s')
            new_values.append(value)
    sql = sql % tuple(placeholders)
    values = tuple(new_values)

    # ... cursor.execute(sql, values)

list_of_ids = [ 1, 2, 3]
query = "select * from table where x in %s" % str(tuple(list_of_ids))
print query

쿼리 문자열을 완성하기 위해 인수를 전달해야하는 메서드에 관심이없고 .NET 만 호출하려는 경우 일부 사용 사례에서 작동 할 수 있습니다 cursror.execute(query).

다른 방법은 다음과 같습니다.

"select * from table where x in (%s)" % ', '.join(str(id) for id in list_of_ids)

매우 간단합니다. 아래 구성을 사용하십시오.

rules_id = [ "9", "10"]

sql1 = "SELECT * FROM attendance_rules_staff WHERE id in("+", ".join(map(str, rules_id))+")"

", ".join(map(str, rules_id))

참고URL : https://stackoverflow.com/questions/589284/imploding-a-list-for-use-in-a-python-mysqldb-in-clause

반응형