Я пытаюсь найти лучший способ отформатировать строку запроса sql. Когда я отлаживаю свое приложение, я хочу записать в журнал все строки запроса sql, и важно, чтобы строка была правильно сформирована.
Опция 1
def myquery():
sql = "select field1, field2, field3, field4 from table where condition1=1 and condition2=2"
con = mymodule.get_connection()
...
- Это хорошо для печати строки sql.
- Это не лучшее решение, если строка длинная и не соответствует стандартной ширине в 80 символов.
Вариант 2
def query():
sql = """
select field1, field2, field3, field4
from table
where condition1=1
and condition2=2"""
con = mymodule.get_connection()
...
Здесь код ясен, но когда вы печатаете строку запроса sql, вы получаете все эти раздражающие пробелы.
u '\ nвыбрать field1, field2, field3, field4 \ n_ _ ___ из таблицы \ n _ ___, где condition1 = 1 \ n _ ___ _and condition2 = 2'
Примечание: я заменил пробелы на подчеркивание _
, потому что они обрезаны редактором.
Вариант 3
def query():
sql = """select field1, field2, field3, field4
from table
where condition1=1
and condition2=2"""
con = mymodule.get_connection()
...
- Мне не нравится этот вариант, потому что он нарушает ясность хорошо табулированного кода.
Вариант 4
def query():
sql = "select field1, field2, field3, field4 " \
"from table " \
"where condition1=1 " \
"and condition2=2 "
con = mymodule.get_connection()
...
- Мне не нравится этот вариант, потому что лишний набор текста в каждой строке также затруднен для редактирования запроса.
Для меня лучшим решением будет вариант 2, но мне не нравятся лишние пробелы при печати строки sql.
Вы знаете какие-нибудь другие варианты?
python
sql
string-formatting
солер
источник
источник
Ответы:
Извините за публикацию в такой старой теме, но как человек, который также разделяет страсть к питоническим «лучшим», я подумал, что поделюсь нашим решением.
Решение состоит в том, чтобы создавать операторы SQL с использованием конкатенации строковых литералов Python ( http://docs.python.org/ ), которая может быть квалифицирована где-то между вариантом 2 и вариантом 4.
Пример кода:
sql = ("SELECT field1, field2, field3, field4 " "FROM table " "WHERE condition1=1 " "AND condition2=2;")
Также работает с f-струнами :
fields = "field1, field2, field3, field4" table = "table" conditions = "condition1=1 AND condition2=2" sql = (f"SELECT {fields} " f"FROM {table} " f"WHERE {conditions};")
Плюсы:
источник
"""
и использоватьtextwrap.dedent()
перед"sql query"
чтобы избежать путаницы со строками SQL (которые стандартно используют одинарные кавычки)?Вы, очевидно, рассмотрели множество способов написать SQL так, чтобы он распечатывался нормально, но как насчет изменения оператора print, который вы используете для ведения журнала отладки, вместо того, чтобы писать свой SQL так, как вам не нравится? Используя ваш любимый вариант выше, как насчет такой функции ведения журнала, как эта:
def debugLogSQL(sql): print ' '.join([line.strip() for line in sql.splitlines()]).strip() sql = """ select field1, field2, field3, field4 from table""" if debug: debugLogSQL(sql)
Это также сделало бы тривиальным добавление дополнительной логики для разделения регистрируемой строки на несколько строк, если строка длиннее, чем желаемая длина.
источник
Самый чистый способ, с которым я столкнулся, вдохновлен руководством по стилю sql .
sql = """ SELECT field1, field2, field3, field4 FROM table WHERE condition1 = 1 AND condition2 = 2; """
По сути, ключевые слова, с которых начинается предложение, должны быть выровнены по правому краю, а имена полей и т. Д. Должны быть выровнены по левому краю. Это выглядит очень аккуратно, и его также легче отлаживать.
источник
sql = ("select field1, field2, field3, field4 " "from table " "where condition1={} " "and condition2={}").format(1, 2) Output: 'select field1, field2, field3, field4 from table where condition1=1 and condition2=2'
если значение условия должно быть строкой, вы можете сделать следующее:
sql = ("select field1, field2, field3, field4 " "from table " "where condition1='{0}' " "and condition2='{1}'").format('2016-10-12', '2017-10-12') Output: "select field1, field2, field3, field4 from table where condition1='2016-10-12' and condition2='2017-10-12'"
источник
format()
строк SQL, это сильный запах кода.where condition1=:field1
и последующая передача значений в качестве параметров. Если вы используете.format()
, будет способ';DROP TABLE Users
вставить в ваш SQL. Посмотрите PEP-249, чтобы узнать, как правильно использовать параметры. python.org/dev/peps/pep-0249/#paramstyleВы можете использовать
inspect.cleandoc
для красивого форматирования вашего печатного оператора SQL.Это очень хорошо работает с вашим вариантом 2 .
Примечание:
print("-"*40)
это только для демонстрации лишних пустых строк, если вы не используете cleandoc.from inspect import cleandoc def query(): sql = """ select field1, field2, field3, field4 from table where condition1=1 and condition2=2 """ print("-"*40) print(sql) print("-"*40) print(cleandoc(sql)) print("-"*40) query()
Выход:
---------------------------------------- select field1, field2, field3, field4 from table where condition1=1 and condition2=2 ---------------------------------------- select field1, field2, field3, field4 from table where condition1=1 and condition2=2 ----------------------------------------
Из документов :
источник
Чтобы полностью избежать форматирования , я думаю, что отличным решением является использование процедур .
Вызов процедуры дает вам результат любого запроса, который вы хотите поместить в эту процедуру. Фактически вы можете обрабатывать несколько запросов в рамках процедуры. Вызов просто вернет последний вызванный запрос .
MYSQL
DROP PROCEDURE IF EXISTS example; DELIMITER // CREATE PROCEDURE example() BEGIN SELECT 2+222+2222+222+222+2222+2222 AS this_is_a_really_long_string_test; END // DELIMITER; #calling the procedure gives you the result of whatever query you want to put in this procedure. You can actually process multiple queries within a procedure. The call just returns the last query result call example;
Python
sql =('call example;')
источник
вы можете поместить имена полей в массив "fields", а затем:
sql = 'select %s from table where condition1=1 and condition2=2' % ( ', '.join(fields))
источник
Я бы посоветовал придерживаться варианта 2 (я всегда использую его для более сложных запросов
SELECT * FROM table
), и если вы хотите распечатать его красиво, вы всегда можете использовать отдельный модуль .источник
Для коротких запросов, которые могут уместиться в одну или две строки, я использую решение строкового литерала в решении, получившем наибольшее количество голосов выше. Для более длинных запросов я разбиваю их на
.sql
файлы. Затем я использую функцию-оболочку для загрузки файла и выполнения сценария, например:script_cache = {} def execute_script(cursor,script,*args,**kwargs): if not script in script_cache: with open(script,'r') as s: script_cache[script] = s return cursor.execute(script_cache[script],*args,**kwargs)
Конечно, это часто находится внутри класса, поэтому мне обычно не нужно передавать
cursor
явно. Я также обычно используюcodecs.open()
, но это дает общую идею. Тогда сценарии SQL полностью автономны в своих собственных файлах с собственной подсветкой синтаксиса.источник
sql = """\ select field1, field2, field3, field4 from table where condition1=1 and condition2=2 """
[редактировать в ответ на комментарий]
Наличие строки SQL внутри метода НЕ означает, что вы должны "табулировать" ее:
>>> class Foo: ... def fubar(self): ... sql = """\ ... select * ... from frobozz ... where zorkmids > 10 ... ;""" ... print sql ... >>> Foo().fubar() select * from frobozz where zorkmids > 10 ; >>>
источник
select
. В моем ответе нет ведущих пробелов. Что привело вас к мнению, что они одинаковы?