Параметризированные запросы MySQL

Ваш вопрос заключается в том, как обработать этот тип запроса или ошибки. Итак, вот мое предложение общей стратегии.

Сначала сделай свою домашнюю работу. Например, вы можете легко найти этот прошлый вопрос . Если вы уже пробовали способ, но обнаружили, что он не работает, вы должны были описать, что вы сделали, а что не сработало в вашем вопросе.

Теперь, я предполагаю, что вы можете воспроизвести случай или, по крайней мере, вы можете ожидать, что столкнетесь с той же проблемой в ближайшем будущем (или вы можете подождать до тех пор), чтобы у вас было больше шансов определить проблему в следующий раз. , Если вы знаете, какие параметры вызвали ошибку, я думаю, вы можете воспроизвести случай в вашей среде разработки. Однако, если нет, то это более сложно определить - это сильно зависит от того, сколько информации об ошибке и входных данных у вас есть, и какую среду разработки вы можете использовать, и мой ответ не охватывает этот случай.

Первая цель должна состоять в том, чтобы определить, какая именно команда (метод) в вашем коде вызвала ошибку. Это произошло только внутри Rails или ваша БД вызвала ошибку? В вашем конкретном случае это произошло в Step.find_by или @step.update или еще? Что такое steps_params? Это похоже на метод, который вы определили. Вы уверены, что steps_params работает как положено? (Вы можете быть уверены, но мы не знаем…)

Удобный способ выяснить это - просто вставить logger.debug (или logger.error) и т. Д. До и после каждого предложения. При этом рекомендуется в некоторых случаях разбивать предложение на более мелкие единицы. Например, steps_params и update() должны быть разделены, например (в простейшем случае),

logger.debug 'Before steps_params'
res_steps_params = steps_params
logger.debug 'Before update'
res_update = @step.update(res_steps_params)
logger.debug 'Before if'
if res_update
  # ……

Очевидно, что вы можете (и, возможно, должны) регистрировать более подробную информацию, такую ​​как, [119 ], и вы также можете заключить деталь с предложением begin - rescue, чтобы вы могли получить подробную информацию об исключении и записать его в журнал. Также я могу порекомендовать разделить update на 2 части - замены и save - чтобы точно определить, какое действие и параметр вызывают проблему.

Как только вы выяснили, какая из БД или Rails или что-то раньше (например, HTTP-сервер или клиент-браузер) виновата, а какой параметр вызывает проблему, вы можете перейти к следующему этапу. Сообщение об ошибке предполагает, что это проблема кодировки символов. Является ли кодировка символов строки недопустимой (как UTF-8) или неправильно распознанной Rails (что может быть не ошибкой Rails, а клиента), или неправильно распознана БД?

Где бы ни находилась проблема, обычно (хотя и не всегда!) Можно исправить или обойти проблемы кодировки символов с помощью Ruby (Rails). Методы Ruby из , String#encode, , , String#encoding, и String#force_encoding были бы полезны для диагностики и, возможно, решения проблемы.

В качестве дополнительного примечания может быть полезно, если возможно, в вашей среде, просмотреть файл журнала вашей БД (PostgreSQL?), Чтобы выяснить, какой запрос, переданный из Rails в БД, вызвал проблему (если запрос действительно был перешел к ним!). В качестве альтернативы, Rails Gem SQL Query Tracker может быть полезен для того, чтобы узнать, какие запросы создает ваше приложение Rails (хотя я никогда не использовал его и поэтому не могу много рассказать.)

В конце В тот день, когда код ведет себя странным образом, я боюсь, что только верный способ решить - сузить проблемный пункт или параметр шаг за шагом. Удачи!

76
задан codeforester 18 December 2018 в 23:46
поделиться

3 ответа

Остерегайтесь использования строковой интерполяции для запросов SQL, поскольку она не будет корректно экранировать входные параметры и оставит ваше приложение открытым для уязвимостей внедрения SQL. Разница может показаться тривиальной, но на самом деле она огромна .

Неверно (с проблемами безопасности)

c.execute("SELECT * FROM foo WHERE bar = %s AND baz = %s" % (param1, param2))

Правильно (с экранированием)

c.execute("SELECT * FROM foo WHERE bar = %s AND baz = %s", (param1, param2))

Это добавляет путаницу к тому, что модификаторы используются для привязки параметров в операторе SQL различается между различными реализациями API БД и тем, что клиентская библиотека mysql использует синтаксис стиля printf вместо более распространенного «?» маркер (используется, например, python-sqlite ).

246
ответ дан 24 November 2019 в 11:02
поделиться

У вас есть несколько доступных вариантов. Вы захотите освоиться с итерполяцией строки Python. Какой термин вы могли бы более успешно искать в будущем, когда хотите узнать что-то вроде этого.

Лучше для запросов:

some_dictionary_with_the_data = {
    'name': 'awesome song',
    'artist': 'some band',
    etc...
}
cursor.execute ("""
            INSERT INTO Songs (SongName, SongArtist, SongAlbum, SongGenre, SongLength, SongLocation)
            VALUES
                (%(name)s, %(artist)s, %(album)s, %(genre)s, %(length)s, %(location)s)

        """, some_dictionary_with_the_data)

Учитывая, что у вас, вероятно, уже есть все ваши данные в объекте или словаре, второй формат подойдет вам лучше. Также отстойно, что приходится подсчитывать «% s» появления в строке, когда вам нужно вернуться и обновить этот метод через год:)

44
ответ дан 24 November 2019 в 11:02
поделиться

Связанные документы дают следующий пример:

   cursor.execute ("""
         UPDATE animal SET name = %s
         WHERE name = %s
       """, ("snake", "turtle"))
   print "Number of rows updated: %d" % cursor.rowcount

Итак, вы просто нужно адаптировать это к вашему собственному коду - пример:

cursor.execute ("""
            INSERT INTO Songs (SongName, SongArtist, SongAlbum, SongGenre, SongLength, SongLocation)
            VALUES
                (%s, %s, %s, %s, %s, %s)

        """, (var1, var2, var3, var4, var5, var6))

(Если SongLength является числовым, вам может потребоваться использовать% d вместо% s).

14
ответ дан 24 November 2019 в 11:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: