Python - выберите из таблиц sqlite, передав несколько аргументов - PullRequest
0 голосов
/ 25 февраля 2020

Я пытаюсь создать веб-приложение в Flask и SQLite, и у меня есть таблица со столбцами: Дата, Страна и Имя, и я делаю форму запроса на эти данные

country = request.form.getlist('country')
name = request.form.getlist('name')

str_from_date = request.form.get('from_date')
str_to_date = request.form.get('to_date')
from_date = dt.datetime.strptime(str_from_date, '%d/%m/%Y')
to_date = dt.datetime.strptime(str_to_date, '%d/%m/%Y')

И Я пытаюсь передать эти аргументы в sql оператор выбора, т.е.

SELECT * FROM table WHERE country_col IN {country} AND name_col IN {name}
AND date(date_col) >= {from_date} AND date(date_col) <= {to_date}

Но я не могу найти способ сделать это при передаче более одного аргумента, так что сейчас все, что у меня есть, это потому что cur.execute не принимает более одного аргумента

sql = 'SELECT * FROM table WHERE country_col IN ({co}) ORDER BY datetime(date_col) ASC'.format(co=','.join(['?'] * len(country)))
data = cur.execute(sql, country).fetchall()

Я хочу, чтобы я мог передать несколько аргументов в оператор sql select, чтобы запросить данные соответственно

Ответы [ 2 ]

0 голосов
/ 25 февраля 2020

Первый способ, которым я бы подумал сделать это, - это сгенерировать запрос вручную:

country = {
  "col": col1,
  "type": None, 
  "q": "IN", 
  "data": request.form.getlist('country')
}

name = {
  "col": col2, 
  "type": None, 
  "q": "IN", 
  "data": request.form.getlist('name')
}

str_from_date = request.form.get('from_date')
str_to_date = request.form.get('to_date')

from_date = {
  "col": col3, 
  "type": "date", 
  "q": ">=", 
  "data": dt.datetime.strptime(str_from_date, '%d/%m/%Y')
}

to_date = {
  "col": col4, 
  "type": "date", 
  "q": "<=", 
  "data": dt.datetime.strptime(str_to_date, '%d/%m/%Y')
}

all_data = [country, name_col, from_date, to_date]

q = "SELECT * FROM table WHERE "

for i, d in enumerate():
  _col = f"date({d['col']})" if d["type"] == "date" else d["col"]
  q += f"{'AND ' if i > 0 else ''}{d['col']} {d['q']} ({['?'] * len(d['data'])}) "

data = cur.execute(q, [d["data"] for d in all_data]).fetchall()

Я не знаю, является ли это желаемым подходом, но я думаю, что он будет работать.

0 голосов
/ 25 февраля 2020

Вы можете запустить SQL для своего экземпляра SQLite вместо Python. Таким образом, легче найти проблему с оператором SQL - на один уровень меньше.

Я вижу потенциальную проблему с синтаксисом вашего запроса. Когда используется {country}, то Python помещает Canada, Poland в качестве строки. Однако SQLite ожидает значение, которое должно быть 'Canada', 'Poland'.

Кроме того, что оператор IN проверяет, существует ли поле в предоставленном списке - поэтому вам нужно (, ) - для построения списка с одним элементом. Лучший оператор здесь =.

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

След. Я не уверен, что хранится в from_date / to_date столбцах. Пожалуйста, прочитайте Документы SQLite , чтобы убедиться, что он используется правильно.

Итак, с предлагаемыми изменениями я хотел бы видеть:

sql = f"""SELECT * 
 FROM table 
 WHERE country_col = '{country}' 
  AND name_col = '{name}'
  AND date(date_col) BETWEEN '{from_date}' AND '{to_date}'"""

Обновление

Передать массив. Давайте начнем с basi c SQL:

выберите * из таблицы, где страна_кол в ('Польша', 'Канада', 'Германия')

Чтобы узнать больше, отметьте этот сайт. Просто помните, что строка должна быть окружена '. Иногда это может быть также ", но для PostgreSQL "col" - означает имя столбца col, а 'col' означает строку col. Итак, ваш оператор IN был правильным!

Теперь с Python - вам нужно подготовить строку с названиями стран, каждая из которых будет окружена ':

countries = ['Poland', 'Germany', 'France']
param = ", ".join([f"'{x}'" for x in countries])                                                                                                                                                                                           

join объединяет строки из переданного списка, внутреннее понимание добавляет ' к каждому элементу списка.

Вместе:

countries = ['Poland', 'Germany', 'France']
param = ", ".join([f"'{x}'" for x in countries])                                                                                                                                                                                           
sql = f"""SELECT * 
 FROM table 
 WHERE country_col in ({param})' 
  AND name_col = '{name}'
  AND date(date_col) BETWEEN '{from_date}' AND '{to_date}'"""
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...