Формат строки% s в длинном запросе с многократным использованием нескольких переменных - PullRequest
1 голос
/ 11 июля 2020

Я читаю этот сообщение SO, а также выполняю поиск.

Я использую psycopg2 для выполнения строк как sql запросов:

import credentials as creds
import psycopg2
start_date = '2020-01-01'
end_date = '2020-01-02'
another_date = '2019-12-31'


my_sql_query = """

with 

t1 as (
select * 
from table
where date >= %s), # should be start_date

t2 as (
select *
from anothertable
where created_date >= %s # should be start_date
and created_date <= %s # should be end_date
)

t3 as (
select *
from anotheranothertable
where date >= %s # should be another_date
)

select t1.blah, t2.ha, t3.*
from t1
join t2 on t2.id = t1.id
join t3 on t3.id = t1.id

"""

Тогда

cursor.execute(my_sql_query, (start_date, end_date, another_date))

Здесь 4% s экземпляров. На самом деле у меня есть 3 переменные для них:

start_date
end_date
another_date

Фактический запрос, который я использую, длиннее и повсюду делает несколько ссылок на эти 3 переменные даты.

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

На основе приведенного выше примера, если я повторю ссылку на переменную, мне придется вызвать cursor.execute с переменными в порядок их появления, включая повторения:

cursor.execute(my_sql_query, (start_date, start_date, end_date, another_date))

Но в моем реальном скрипте он стал бы намного длиннее, например

cursor.execute(my_sql_query, (start_date, start_date, end_date, another_date, start_date, end_date, end_date, another_date, start_date))

Каков «правильный» подход к этому?

Ответы [ 2 ]

3 голосов
/ 11 июля 2020

Вы можете просто сначала заполнить переменные самостоятельно, а затем вызвать cursor.execute().

start_date = '2020-01-01'
end_date = '2020-01-02'
another_date = '2019-12-31'

date_map = {}
date_map['start_date'] = start_date
date_map['end_date'] = end_date
date_map['another_date'] = another_date

my_sql_query = """

with 

t1 as (
select * 
from table
where date >= {start_date}), # should be start_date

t2 as (
select *
from anothertable
where created_date >= {start_date} # should be start_date
and created_date <= {end_date} # should be end_date
)

t3 as (
select *
from anotheranothertable
where date >= {another_date} # should be another_date
)

select t1.blah, t2.ha, t3.*
from t1
join t2 on t2.id = t1.id
join t3 on t3.id = t1.id

"""

my_sql_query = my_sql_query.format(**date_map)
#cursor.execute(my_sql_query)
print(my_sql_query)
1 голос
/ 04 августа 2020

Вы можете использовать это, чтобы повторить его в SQL и заставить API базы данных обрабатывать замену более безопасным способом:

Параметризованные запросы с psycopg2 / Python DB-API и PostgreSQL

...