Форматирование строки запроса 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 64

10 ответов:

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

решение заключается в создании операторов SQL с использованием конкатенации строковых литералов python (http://docs.python.org/), который может быть квалифицирован где-то между вариантом 2 и вариантом 4

Код:

sql = ('select field1, field2, field3, field4 '
       'from table '
       'where condition1=1 '
       'and condition2=2 ')

плюсы:

  1. он сохраняет питонический "хорошо табулированный" форматировать, но не добавлять посторонние символы пробела (что загрязняет ведение журнала).
  2. это позволяет избежать продолжения обратной косой черты уродства варианта 4, что затрудняет добавление утверждений (не говоря уже о слепоте белого пространства).
  3. и далее, очень просто развернуть оператор в 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])
             )

Я бы предложил очень простой вариант. просто поставить r перед строкой Вы можете использовать его, как показано ниже:

query=(r'SELECT f1,f2,f3 '
     r'FROM table1 '
     r'WHERE f4=cond1 '
     r'AND f5=cond2 ')
cursor.execute(str(query))
results=cursor.fetchall()
cursor.close()