2012-07-06 11 views
7

W jaki sposób mogę uniknąć wprowadzania danych wejściowych do bazy danych MySQL db w Python3? Używam PyMySQL i działa dobrze, ale gdy próbuję zrobić coś takiego:Jak mogę uniknąć danych wejściowych do MySQL db w Python3?

cursor.execute("SELECT * FROM `Codes` WHERE `ShortCode` = '{}'".format(request[1])) 

to nie będzie działać, jeśli ciąg ma ' lub ". Próbowałem również:

cursor.execute("SELECT * FROM `Codes` WHERE `ShortCode` = %s",request[1]) 

Problem polega na tym, że biblioteka (PyMySQL) wykorzystuje składnię formatowania Python2.x, %, że już nie działa. Znalazłem także to możliwe rozwiązanie

conn.escape_string() 

w here, ale nie wiem gdzie dodać tego kodu. To wszystko co mam:

import pymysql 
import sys 
conn = pymysql.connect(host = "localhost", 
      user = "test", 
      passwd = "", 
      db  = "test") 
cursor = conn.cursor() 
cursor.execute("SELECT * FROM `Codes` WHERE `ShortCode` = {}".format(request[1])) 

result = cursor.fetchall() 

cursor.close() 
conn.close() 

Edit: I rozwiązać go! W PyMySQL właściwa droga jest tak:

import pymysql 
import sys 
conn = pymysql.connect(host="localhost", 
      user="test", 
      passwd="", 
      db="test") 
cursor = conn.cursor() 
text = conn.escape(request[1]) 
cursor.execute("SELECT * FROM `Codes` WHERE `ShortCode` = {}".format(text)) 

cursor.close() 
conn.close() 

Jeżeli linia text = conn.escape(request[1]) co wymyka się kod. Znalazłem go w kodzie PyMySQL. Tam wejściem jest request[1].

+1

Cool. Powinieneś jednak opublikować drugą połowę swojego pytania jako odpowiedź. Możesz zaakceptować własną odpowiedź. – Grilse

+0

Ups, nie widziałem tego przycisku wcześniej. – user1460016

+0

Jeśli zostanie rozwiązany, oznacz flagę jako zaakceptowane. :-) – Jocelyn

Odpowiedz

6

Rozwiązany. W PyMySQL właściwa droga jest tak:

import pymysql 
import sys 
conn = pymysql.connect(host="localhost", 
      user="test", 
      passwd="", 
      db="test") 
cursor = conn.cursor() 
text = conn.escape(request[1]) 
cursor.execute("SELECT * FROM `Codes` WHERE `ShortCode` = {}".format(text)) 

cursor.close() 
conn.close() 

Jeżeli linia text = conn.escape(request[1]) co wymyka się kod. Znalazłem go w kodzie PyMySQL. Tam wejściem jest request[1].

14

Mimo że odpowiedź "rozwiązana" działa, nie jest to najlepsza praktyka. Korzystając z biblioteki zgodnej z DBI Pythona, powinieneś używać zmiennych bind, zamiast formatować ciąg znaków i przekazywać go do wykonania. W tej metodologii są zagrożenia.

Dlatego jest to dobry sposób, żeby to zrobić:

cursor.execute("SELECT * FROM `Codes` WHERE `ShortCode` = %s", text) 

Zauważ, że nie jest to ciąg formatu, ale zmienna wiążą przekazywane do kursora wykonującego.

Szczegółowe informacje: Python DBI PEP

+0

Należy zauważyć, że "% s" powinno być używane nawet z różnymi typami, na przykład liczbami całkowitymi. Próbowałem użyć "% d" i otrzymałem błąd: '% d format: wymagana jest liczba, a nie str.". – nephets

0

Gotowy do użycia funkcji pomocnika

def mysql_insert(conn, table, row): 
    cols = ', '.join('`{}`'.format(col) for col in row.keys()) 
    vals = ', '.join('%({})s'.format(col) for col in row.keys()) 
    sql = 'INSERT INTO `{0}` ({1}) VALUES ({2})'.format(table, cols, vals) 
    conn.cursor().execute(sql, row) 
    conn.commit() 

Przykład użycia

insert_into(conn, 'people', { 
    'firstname': 'John', 
    'lastname': 'Doe', 
    'age': 18, }) 

referencyjny: https://github.com/PyMySQL/PyMySQL/blob/master/pymysql/cursors.py#L157-L158

def execute(self, query, args=None):

If args is a list or tuple, %s can be used as a placeholder in the query. 
If args is a dict, %(name)s can be used as a placeholder in the query.