Python SQL форматирование строки запроса - PullRequest
75 голосов
/ 09 марта 2011

Я пытаюсь найти лучший способ отформатировать строку запроса 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Выберите поле1, поле2, поле3, поле4 \ n_ _ ___ из таблицы \ n _ ___ , где условие1 = 1 \ n _ ___ _и условие2 = 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.

Известны ли вам какие-либо другие варианты?

Ответы [ 11 ]

111 голосов
/ 24 февраля 2012

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

Решение состоит в том, чтобы создавать операторы SQL с использованием констатации букв Python String (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 , чтобы открыть новую строку).
17 голосов
/ 09 марта 2011

Вы, очевидно, рассмотрели множество способов написания 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)

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

2 голосов
/ 12 мая 2016
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'"
1 голос
/ 20 января 2016

Самый чистый способ, с которым я столкнулся, вдохновлен руководством по стилю sql .

sql = """
    SELECT field1, field2, field3, field4
      FROM table
     WHERE condition1 = 1
       AND condition2 = 2;
"""

По сути, ключевые слова, начинающие предложение, должны быть выровнены по правому краю, а имена полей и т. Д. Должны быть выровнены по левому краю. Это выглядит очень аккуратно и его легче отлаживать.

0 голосов
/ 13 декабря 2018

Чтобы избежать полного форматирования , я думаю, что отличным решением является использование процедур .

Вызов процедуры дает вам результат любого запроса, который вы хотите поставить в этой процедуре. На самом деле вы можете обрабатывать несколько запросов внутри процедуры. Вызов просто вернет последний запрос , который был вызван.

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;')
0 голосов
/ 07 октября 2016

Я бы предложил очень простой вариант. просто поставьте 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()
0 голосов
/ 19 января 2015

В дополнение к @ 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])
             )
0 голосов
/ 17 декабря 2013

Для коротких запросов, которые могут уместиться в одну или две строки, я использую строковое литеральное решение в решении с высоким рейтингом выше. Для более длинных запросов я разбиваю их на .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 полностью автономны в своих собственных файлах с собственной подсветкой синтаксиса.

0 голосов
/ 09 марта 2011

Я бы предложил придерживаться варианта 2 (я всегда использую его для запросов, более сложных, чем SELECT * FROM table), и если вы хотите распечатать его хорошим способом, вы всегда можете использовать отдельный модуль .

0 голосов
/ 09 марта 2011
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
;
>>>
...