복붙노트

[PYTHON] 파이썬 MySQLDB IN 절에서 사용할리스트를 imploding하기

PYTHON

파이썬 MySQLDB IN 절에서 사용할리스트를 imploding하기

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

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

그리고 다음 문자열을 IN 절로 가져올 수 있다는 것을 알고 있습니다.

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

내가 필요한 것은 SQLDB를 사용하여 안전하게 동일한 작업을 수행하는 것입니다. 위의 예제에서 foostring은 실행 인수로 전달되지 않으므로 취약합니다. 나는 또한 mysql 라이브러리 밖에서 인용하고 이스케이프해야한다.

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

해결법

  1. ==============================

    1.list_of_ids를 직접 사용하십시오.

    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의 드라이버로 직접 전달되므로 쿼리 텍스트가 아닌 매개 변수로 사용되므로 주입이 없다는 점에 유의하십시오. 문자열에 원하는 문자를 남기거나 문자를 제거하거나 인용 할 필요가 없습니다.

  2. ==============================

    2.고통없는 MySQLdb execute ( '... WHERE name1 = % s AND name2 IN (% s)', value1, values2)

    고통없는 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)
    
  3. ==============================

    3.이 사람이 제안한 것처럼 (MySQLdb를 사용하여 "SELECT ... WHERE ... IN ..."을 실행), itertools.repeat ()를 사용하여 [% s의 목록을 생성하는 것보다 [[% s '] 목록 (특히 map () 사용보다 훨씬 빠름), 특히 긴 목록의 경우.

    이 사람이 제안한 것처럼 (MySQLdb를 사용하여 "SELECT ... WHERE ... IN ..."을 실행), itertools.repeat ()를 사용하여 [% s의 목록을 생성하는 것보다 [[% s '] 목록 (특히 map () 사용보다 훨씬 빠름), 특히 긴 목록의 경우.

    in_p = ', '.join(itertools.repeat('%s', len(args)))
    

    이 시간은 인텔 코어 i5 CPU M540 @ 2.53GHz x 4가 장착 된 파이썬 2.7.3을 사용하여 수행되었습니다.

    >>> timeit.timeit("repeat('%s', len(short_list))", 'from itertools import repeat; short_list = range(3)')
    0.20310497283935547
    >>> timeit.timeit("['%s'] * len(short_list)", 'short_list = range(3)')
    0.263930082321167
    >>> timeit.timeit("list(map(lambda x:'%s', short_list))", 'short_list = range(3)')
    0.7543060779571533
    
    
    >>> timeit.timeit("repeat('%s', len(long_list))", 'from itertools import repeat; long_list = range(1000)')
    0.20342397689819336
    >>> timeit.timeit("['%s'] * len(long_list)", 'long_list = range(1000)')
    4.700995922088623
    >>> timeit.timeit("list(map(lambda x:'%s', long_list))", 'long_list = range(1000)')
    100.05319118499756
    
  4. ==============================

    4.

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

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

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

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

    5.아주 간단합니다 : 아래의 양식을 사용하십시오.

    아주 간단합니다 : 아래의 양식을 사용하십시오.

    rules_id = [ "9", "10"]

    sql1 = "SELECT * FROM attendance_rules_staff 어디에서 ("+ ",". 조인 (map (str, rules_id)) + ")"

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

  6. from https://stackoverflow.com/questions/589284/imploding-a-list-for-use-in-a-python-mysqldb-in-clause by cc-by-sa and MIT license