Python, MySQLdb и экранирование имен таблиц? - PullRequest
7 голосов
/ 08 июля 2011

Возможно, мне не хватает чего-то очевидного, но я не могу понять, чем мой код отличается от различных примеров, которые я вижу в онлайн-документации для MySQLdb.

Я довольно новичок в программировании на python, более опытный в perl. То, что я пытаюсь сделать, это получить определенные хорошие привычки на раннем этапе (как в Perl, я всегда начинаю с «использовать строгий; используйте предупреждения»), поэтому я стараюсь создать многократно используемые функции в независимом файле ( funct.py), чтобы потом сэкономить время.

У меня есть эта функция для выбора случайных строк из таблицы:

def returnRandom(conn,countcol,table,field):
    cursor = conn.cursor()
    cursor.execute('SELECT MAX(%s) FROM %s',(countcol,table))
    maxRow = cursor.fetchone()[0]
    cursor.execute("SELECT MIN(%s) FROM %s",(countcol,table))
    minRow = cursor.fetchone()[0]
    randomId = random.randrange(minRow,maxRow+1,1)
    cursor.execute("SELECT ? FROM ? WHERE id >=? LIMIT 1",field,table,randomId)
    return cursor.fetchone()[0]

Это называется так:

msg = funct.returnRandom(conn,"id","testtable","data")

К сожалению, это приводит к ошибкам: _mysql_exceptions.ProgrammingError: (1064, «у вас есть ошибка в синтаксисе SQL; проверьте руководство, соответствующее вашей версии сервера MySQL, на предмет правильного синтаксиса для использования рядом с« testtable »в строке 1»)

Если я помещу testtable вместо% s в строке выполнения, запрос будет выполнен, но, похоже, он будет работать

SELECT MAX('id') FROM testtable;

который, конечно, возвращает 'id'.

С учетом того, что он выглядит так, как будто он цитирует записи% s, когда пытается их выполнить. Мне было интересно, может ли кто-нибудь объяснить, как я могу прекратить это делать, или как мне на самом деле делать то, чего я пытаюсь достичь? Я хочу, чтобы функция была настолько универсальной, насколько это возможно, поэтому полагаюсь на данные, передаваемые ей при вызове.

edit: я должен добавить, если я подставлю в? метки:

....
    cursor.execute('SELECT MAX(?) FROM ?',(countcol,table))
File "/usr/lib/pymodules/python2.7/MySQLdb/cursors.py", line 151, in execute
    query = query % db.literal(args)
TypeError: not all arguments converted during string formatting

Ответы [ 3 ]

2 голосов
/ 08 июля 2011

Нельзя использовать DB-API для метаданных;вам нужно будет сделать замену самостоятельно вне вызова execute().

query = 'SELECT MAX(%%s) FROM `%s`' % (table,)
cursor.execute(query, (countcol,))

Очевидно, что вам не следует делать это, если table поступает из внешнего источника.

0 голосов
/ 06 мая 2015

Интересно.Но в руководстве есть пара примеров.Может быть, это что-то похожее.

c=db.cursor()
max_price=5
c.execute("""SELECT spam, eggs, sausage FROM breakfast
          WHERE price < %s""", (max_price,))

В этом примере max_price = 5 Зачем тогда использовать% s в строке?Потому что MySQLdb преобразует его в литеральное значение SQL, которое представляет собой строку «5».Когда он закончится, запрос на самом деле скажет: "... ГДЕ цена <5". </p>

И

c.executemany(
      """INSERT INTO breakfast (name, spam, eggs, sausage, price)
      VALUES (%s, %s, %s, %s, %s)""",
      [
      ("Spam and Sausage Lover's Plate", 5, 1, 8, 7.95 ),
      ("Not So Much Spam Plate", 3, 2, 0, 3.95 ),
      ("Don't Wany ANY SPAM! Plate", 0, 4, 3, 5.95 )
      ] )

Здесь мы вставляем три строки по пятьценности.Обратите внимание, что существует сочетание типов (строки, целые, числа с плавающей запятой), хотя мы все еще используем только% s.Также обратите внимание, что мы включили строки формата только для одной строки.MySQLdb выбирает их и дублирует для каждой строки.

0 голосов
/ 08 июля 2011

MySQLdb, вероятно, заключает в кавычки имена таблиц в одинарных кавычках, а не в обратных галочках. Попробуйте это

cursor.execute('SELECT MAX(%%s) FROM `%s`' % table,(countcol))
...