Python SQL查询字符串格式

时间:2011-03-09 09:20:09

标签: python sql string-formatting

我正在尝试找到格式化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选择来自表格 _ ___ 其中condition1 = 1 \ n _ ___ _和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字符串时,我不喜欢额外的空格。

你知道其他任何选择吗?

13 个答案:

答案 0 :(得分:106)

很抱歉发布了这么老的帖子 - 但是作为一个对pythonic'最佳'有共同兴趣的人,我想我会分享我们的解决方案。

解决方案是使用python的String Literal Concatenation(http://docs.python.org/)构建SQL语句,该语句可以在选项2和选项4之间的某个位置进行限定

代码示例:

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

优点:

  1. 它保留了pythonic'well wellulated'格式,但不添加无关的空格字符(污染日志记录)。
  2. 它避免了选项4的反斜杠延续丑陋,这使得添加语句变得困难(更不用说空白盲目性)。
  3. 此外,在VIM中扩展语句非常简单(只需将光标定位到插入点,然后按 SHIFT-O 打开一个新行)。

答案 1 :(得分:17)

您显然已经考虑过很多编写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 :(得分:1)

我遇到的最干净的方式受到sql style guide的启发。

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

基本上,开始子句的关键字应该是右对齐的,字段名称等应该保持对齐。这看起来非常整洁,也更容易调试。

答案 3 :(得分:1)

您可以使用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
----------------------------------------

来自docs

inspect.cleandoc(doc)

从缩进以与代码块对齐的文档字符串中清除缩进。

所有前导空格从第一行中删除。可以从第二行开始均匀删除的所有前导空格都将被删除。随后删除开头和结尾的空行。另外,所有选项卡都展开为空格。

答案 4 :(得分:0)

您可以将字段名称放入数组“字段”中,然后:


sql = 'select %s from table where condition1=1 and condition2=2' % (
 ', '.join(fields))

答案 5 :(得分:0)

sql = """\
select field1, field2, field3, field4
from table
where condition1=1
and condition2=2
"""

[编辑回应评论]
在方法中包含SQL字符串并不意味着您必须“制表”itp>

>>> class Foo:
...     def fubar(self):
...         sql = """\
... select *
... from frobozz
... where zorkmids > 10
... ;"""
...         print sql
...
>>> Foo().fubar()
select *
from frobozz
where zorkmids > 10
;
>>>

答案 6 :(得分:0)

我建议坚持选项2(我总是将它用于比SELECT * FROM table更复杂的查询),如果你想以一种很好的方式打印它,你可能总是使用separate module

答案 7 :(得分:0)

对于可以放在一行或两行上的简短查询,我在上面的最高投票解决方案中使用字符串文字解决方案。对于较长的查询,我将其分解为.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脚本完全自包含在他们自己的文件中,并带有自己的语法高亮显示。

答案 8 :(得分:0)

除了@ 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])
             )

答案 9 :(得分:0)

我建议一个非常简单的选择。只需在字符串前添加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()

答案 10 :(得分:0)

为避免完全格式化,我认为一个不错的解决方案是使用procedures

调用过程将为您提供要放入此过程中的任何查询的结果。您实际上可以在一个过程中处理多个查询。呼叫将仅返回最后一个查询

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;')

答案 11 :(得分:0)

使用“ sqlparse”库,我们可以格式化sql。

>>> import sqlparse
>>> raw = 'select * from foo; select * from bar;'
>>> print(sqlparse.format(raw, reindent=True, keyword_case='upper'))
SELECT *
FROM foo;

SELECT *
FROM bar;

参考:https://pypi.org/project/sqlparse/

答案 12 :(得分:0)

这是@aandis 答案的略微修改版本。当涉及到原始字符串时,在字符串前加前缀 'r' 字符。例如:

SELECT IIF('string_1' = 'string_1', 'OK' , 'string_2')

当您的查询包含任何需要转义的特殊字符(如“\”)和 flake8 等 lint 工具将其报告为错误时,建议使用此方法。