Как подставить значение в запрос sqlite?

Ссылка скопирована
1 ответ

Здравствуйте, столкнулся с проблемой невозможности подставить значение в сам sql запрос используя '?'. Приведу похожий код ради наглядности:

#нерабочий код result = cur.execute('SELECT ? FROM messages ORDER BY id DESC LIMIT 1', (value,)).fetchone() #value = 'message_time ' #рабочий код result = cur.execute('SELECT message_time FROM messages ORDER BY id DESC LIMIT 1').fetchone()

#нерабочий код result = cur.execute('SELECT ? FROM messages ORDER BY id DESC LIMIT 1', (value,)).fetchone() #value = 'message_time ' #рабочий код result = cur.execute('SELECT message_time FROM messages ORDER BY id DESC LIMIT 1').fetchone()

Ошибка при попытке конвертировать в int:
ValueError: invalid literal for int() with base 10: 'message_time'

Дополнительно:

Имена полей подставлять нельзя.

  • Можете пожалуйста предложить решение с подставлением, в контексте моей программы это достаточно важно
  • Uadfl, изменить свой подход к структуре таблиц. Поля как правило не должны подставляться динамически, при запросе уже известно, какое поле за что отвечает. А что конкретно изменить, не известно, пока не опишете, для чего вам понадобилось динамически выбирать поля, зачем вообще так решили сделать.
  • o5a, если коротко, то есть функция, которая должна возвращать значение из передаваемого ей столбца
  • Uadfl, а зачем нужна такая функция?
    Это действительно не очень хорошее решение в большинстве ситуаций.
  • функция, которая должна возвращать значение из передаваемого ей столбца

    Получай всю запись, все поля, а на стороне клиента выбирай оттуда только нужное поле.

  • Akina, не надо советовать такие плохие решения... особенно если там таблица с сотнями полей или блобами в них на мегабайты.
  • rPman, крайне мало фреймворков позволяет динамически подставлять имена объектов. Так что альтернативой будет разве что монстрообразный (для таблицы с сотнями полей) CASE.
  • rPman, ну, блобы - штука относительно редкая, а в остальном это лучше, чем сборка строки запроса.
  • Сергей Горностаев, нужно понимать, почему именно считается плохим тоном генерация sql запроса вместо параметризованных и если ни одна из причин не попадает под задачи автора, то почему нет.

    не нужно решать вымышленные проблемы, создавая новые.

    p.s. у sqlite prepared statements не увеличивают производительность (либо это на уровне погрешности), т.е. единственный их бонус - защита от sql иньекций и просто красота кода, не вынуждающая разработчика делать экранирование строк.

  • rPman, прежде всего это идиоматичность. Использование реляционной базы данных подразумевает жёсткую схему БД определённую до рантайма. В очень редких случаях требуется работать в рантайме не с данными, а со схемой, чаще это сигнал плохой архитектуры.
  • Сергей Горностаев, у меня был проект, где пользователь подсовывал свою базу данных (проект древней гис, там шейпы и таблицы), нужно было проанализировать ее структуру, содержимое таблиц и предлагать для выбора таблицы и поля, указывая их назначение, дальше приложение конвертировало эти данные (по факту копирование указанных полей с вариантом объединения таблиц в одну или разделение и выявление справочников).

    Извини, в такой задаче принципиально невозможно заранее подготовить запросы, да и нет в этом смысла.

    так как автор так и не удосужился задачу свою описать, приходится догадываться и предлагать самые невероятные примеры

  • rPman, я и говорю, редкий случай.
  • Uadfl, опять же, Вы озвучили свой способ решения, который как тут уже объяснили, выглядит сомнительно в приложении к реляционным БД. А хотелось бы увидеть, зачем изначально вам такое потребовалось, динамически подставлять названия полей.
    Выглядит как очередная Проблема_XY

    Если простыми словами, это как если бы обратились с вопросом:
    - Как мне укрепить микроскоп, а то он быстро выходит из строя
    - *пожав плечами, предлагают решения по укреплению конструкции микроскопа*
    А на самом деле выясняется, что автор вопроса использовал микроскоп, чтобы забивать гвозди, и правильным ответом на подобный вопрос было бы "использовать молоток", а не пытаться укрепить микроскоп.

  • o5a, ну я понял, спасибо
  • Uadfl, прямым ответом на ваш вопрос будет использовать форматирование строк, например через f-строки, как предложил ниже wincrx, потому что параметризированые запросы (механизм через '?') для подстановки названий идентификаторов в принципе не работает, там только форматировать строку запроса. Просто это в целом не особо правильно делать, и может быть даже опасно, если вы эти названия полей будете не сами жестко контролировать, а брать из ввода пользователя.
    Но если бы объяснили, зачем решили так динамически выбирать названия полей, вам тут могли бы подсказать, как сделать правильно.

Ответы:

Почему ты f-строку не используешь?

result = cur.execute(f'SELECT {value} FROM messages ORDER BY id DESC LIMIT 1').fetchone()

result = cur.execute(f'SELECT {value} FROM messages ORDER BY id DESC LIMIT 1').fetchone()

  • Может по этому?
    Почему не стоит использовать f строки в SQL Python запросах?
  • Михаил Р., в данном случае, особенно если проверять предварительно строчку на ее формат и допустимые названия полей, это нормальное решение для поставленной задачи.

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

Коробочное решение этой задачи называется SQL-Builder.

Вот пример такого https://pypika.readthedocs.io/en/latest/2_tutorial...

Использовать string interpolation здесь технически возможно, но не выдерживает критики
по инфо-безопасности. Атака на инжекцию - это Top 10 уязвимостей софта в 21 веке.

Вот об этом коллеги тоже пишут в ответах.

Нужно решить такую задачу?

Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.

Заказать помощь
Лучший ответ
1
Павел Админов Ответ

Для подстановки значений в запрос SQLite можно использовать параметризированные запросы, чтобы избежать уязвимостей безопасности и предотвратить SQL-инъекции.

Пример параметризированного запроса в PHP:

$db = new SQLite3('database.db');
$stmt = $db->prepare('SELECT * FROM table WHERE column = :value');
$stmt->bindValue(':value', $value, SQLITE3_TEXT);
$result = $stmt->execute();

$db = new SQLite3('database.db'); $stmt = $db->prepare('SELECT * FROM table WHERE column = :value'); $stmt->bindValue(':value', $value, SQLITE3_TEXT); $result = $stmt->execute();

В этом примере мы подготавливаем запрос с помощью метода `prepare()` и затем подставляем значение с помощью метода `bindValue()`. Второй аргумент `SQLITE3_TEXT` указывает на тип данных, который мы ожидаем, но его можно изменить в зависимости от типа данных, который вы хотите использовать.

Если вы работаете с другим языком программирования, то подход будет аналогичным. Главное, чтобы ваш API для работы с SQLite поддерживал параметризированные запросы.

Использование параметризированных запросов не только обеспечивает безопасность вашего приложения, но также повышает производительность за счет кэширования запросов в SQLite.

Другие ответы (0)

Пока нет других ответов. Будьте первым, кто поможет автору.

Ответить на вопрос

комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Вам также может быть интересно