Форматирование строки запроса Python SQL
Я пытаюсь найти лучший способ форматирования строки запроса 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 ' nselect field1, field2, field3, field4n_____из таблицы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.
вы знаете какие-то другие варианты?
10 ответов:
извините за публикацию в такой старой теме - но как человек, который также разделяет страсть к питоническому "лучшему", я думал, что поделюсь нашим решением.
решение заключается в создании операторов SQL с использованием конкатенации строковых литералов python (http://docs.python.org/), который может быть квалифицирован где-то между вариантом 2 и вариантом 4
Код:
sql = ('select field1, field2, field3, field4 ' 'from table ' 'where condition1=1 ' 'and condition2=2 ')
плюсы:
- он сохраняет питонический "хорошо табулированный" форматировать, но не добавлять посторонние символы пробела (что загрязняет ведение журнала).
- это позволяет избежать продолжения обратной косой черты уродства варианта 4, что затрудняет добавление утверждений (не говоря уже о слепоте белого пространства).
- и далее, очень просто развернуть оператор в VIM (просто поместите курсор в точку вставки и нажмите SHIFT-O открыть новую линию).
вы, очевидно, рассмотрели множество способов написать 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'"
вы можете поместить имена полей в массив "поля", а затем:
sql = 'select %s from table where condition1=1 and condition2=2' % ( ', '.join(fields))
Я бы предложил придерживаться варианта 2 (я всегда использую его для запросов более сложных, чем
SELECT * FROM table
) и если вы хотите напечатать его в хорошем виде вы всегда можете использовать отдельные модули.
sql = """\ select field1, field2, field3, field4 from table where condition1=1 and condition2=2 """
[edit in responese to comment]
Наличие строки SQL внутри метода не означает, что вы должны "табулировать" его:>>> class Foo: ... def fubar(self): ... sql = """\ ... select * ... from frobozz ... where zorkmids > 10 ... ;""" ... print sql ... >>> Foo().fubar() select * from frobozz where zorkmids > 10 ; >>>
для коротких запросов, которые могут поместиться на одной или двух строках, я использую решение строкового литерала в верхнем голосовании выше. Для более длинных запросов я разбиваю их на
.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 скрипты полностью автономный в своих собственных файлах с собственной подсветкой синтаксиса.
В дополнение к @user590028:
использование формата было полезно для того, над чем я работал так:
statement = (ins "(name,standard_price,list_price,mes_type,uom_id,uom_po_id,type,procure_method,cost_method_categ_id,supply_method,sale_ok) " "VALUE ('{0}','{1}','{2}'".format(row[1],str(row[2]),str(row[2])) + ",'fixed',1,1,'product','make_to_stock','standard',1,'buy',True) RETURNING id" )
и:
statement = ("INSERT INTO product_product " "(product_tmpl_id,default_code,active,valuation) " "VALUE " "('{0}','{1}',True,'manual_periodic')".format(str(row[0]), row[1]) )