복붙노트

[PYTHON] SQLite "IN"절의 매개 변수 대체

PYTHON

SQLite "IN"절의 매개 변수 대체

IN 절에 대해 Python에서 SQLite로 매개 변수 대체를 사용하려고합니다. 다음은이를 보여주는 완전한 실행 예제입니다.

import sqlite3

c = sqlite3.connect(":memory:")
c.execute('CREATE TABLE distro (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT)')

for name in 'Ubuntu Fedora Puppy DSL SuSE'.split():
  c.execute('INSERT INTO distro (name) VALUES (?)', [ name ] )

desired_ids = ["1", "2", "5", "47"]
result_set = c.execute('SELECT * FROM distro WHERE id IN (%s)' % (", ".join(desired_ids)), ())
for result in result_set:
  print result

출력 :

문서에서는 "[Python의 문자열 연산을 사용하여 쿼리를 조합해서는 안되기 때문에 안전하지 못하며 프로그램이 SQL 삽입 공격에 취약 해집니다. 매개 변수 대체를 사용하려고합니다.

내가 시도 할 때 :

result_set = c.execute('SELECT * FROM distro WHERE id IN (?)', [ (", ".join(desired_ids)) ])

나는 빈 결과 집합을 얻고, 시도 할 때 :

result_set = c.execute('SELECT * FROM distro WHERE id IN (?)', [ desired_ids ] )

나는 얻다:

이 단순화 된 문제에 대한 답변이 효과적이기를 바라지 만 실제로 수행하려는 실제 쿼리는 이중 중첩 된 하위 쿼리에 있음을 지적하고 싶습니다. 위트하려면 :

UPDATE dir_x_user SET user_revision = user_attempted_revision 
WHERE user_id IN 
    (SELECT user_id FROM 
        (SELECT user_id, MAX(revision) FROM users WHERE obfuscated_name IN 
            ("Argl883", "Manf496", "Mook657") GROUP BY user_id
        ) 
    )

해결법

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

    1.올바른 수의? s가 필요하지만 SQL 주입 위험은 없습니다.

    올바른 수의? s가 필요하지만 SQL 주입 위험은 없습니다.

    >>> result_set = c.execute('SELECT * FROM distro WHERE id IN (%s)' %
                               ','.join('?'*len(desired_ids)), desired_ids)
    >>> print result_set.fetchall()
    [(1, u'Ubuntu'), (2, u'Fedora'), (5, u'SuSE')]
    
  2. ==============================

    2.http://www.sqlite.org/limits.html (항목 9)에 따르면 SQLite는 기본적으로 쿼리에 999 개 이상의 매개 변수를 처리 할 수 ​​없으므로 여기에서 솔루션 (자리 표시 자의 필수 목록 생성)은 찾고있는 항목이 수천 개에 이르면 실패합니다. 그렇다면 목록을 해체하고 부분을 반복하여 결과에 직접 참여해야합니다.

    http://www.sqlite.org/limits.html (항목 9)에 따르면 SQLite는 기본적으로 쿼리에 999 개 이상의 매개 변수를 처리 할 수 ​​없으므로 여기에서 솔루션 (자리 표시 자의 필수 목록 생성)은 찾고있는 항목이 수천 개에 이르면 실패합니다. 그렇다면 목록을 해체하고 부분을 반복하여 결과에 직접 참여해야합니다.

    IN 절에 수천 개의 항목이 필요하지 않다면 Alex의 해결책이 그것을 수행하는 방법입니다 (장고가하는 것처럼 보입니다).

  3. ==============================

    3.업데이트 :이 작품 :

    업데이트 :이 작품 :

    import sqlite3
    
    c = sqlite3.connect(":memory:")
    c.execute('CREATE TABLE distro (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT)')
    
    for name in 'Ubuntu Fedora Puppy DSL SuSE'.split():
      c.execute('INSERT INTO distro (name) VALUES (?)', ( name,) )
    
    desired_ids = ["1", "2", "5", "47"]
    result_set = c.execute('SELECT * FROM distro WHERE id IN (%s)' % ("?," * len(desired_ids))[:-1], desired_ids)
    for result in result_set:
      print result
    

    문제는 당신이 가지고 있어야한다는 것이 었습니다. 입력 목록의 각 요소에 대해

    문 ( "?,"* len (desired_ids)) [: - 1]은 "?"의 반복 문자열을 만든 다음 마지막 쉼표를 잘라냅니다. desired_ids의 각 요소에 하나의 물음표가 표시됩니다.

  4. ==============================

    4.나는 항상 이런 식으로 일을 끝낸다.

    나는 항상 이런 식으로 일을 끝낸다.

    query = 'SELECT * FROM distro WHERE id IN (%s)' % ','.join('?' for i in desired_ids)
    c.execute(query, desired_ids)
    

    desired_ids의 문자열을 쿼리에 직접 넣지 않기 때문에 주입 위험이 없습니다.

  5. ==============================

    5.sqlite가 sql 요청의 길이에 문제가있는 경우, 물음표의 개수가 너무 많아서 물건을 부수는 일종의 방법이 될 수 있습니다.

    sqlite가 sql 요청의 길이에 문제가있는 경우, 물음표의 개수가 너무 많아서 물건을 부수는 일종의 방법이 될 수 있습니다.

  6. from https://stackoverflow.com/questions/1309989/parameter-substitution-for-a-sqlite-in-clause by cc-by-sa and MIT license