Python SQL 查询字符串格式设置

我试图找到格式化 sql 查询字符串的最佳方法 我的应用程序,我想记录文件的所有 sql 查询字符串,它是 字符串的格式是否正确非常重要。

选择一

def myquery():
sql = "select field1, field2, field3, field4 from table where condition1=1 and condition2=2"
con = mymodule.get_connection()
...
  • 这有助于打印 sql 字符串。
  • 这不是一个好的解决方案,如果字符串是长的,不符合标准宽度 80个字符。

选择二

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,field4 n _ < em > _ _ _ _从表 n< em > _ _ _ _其中条件1 = 1 n< em > _ _ _ _ _ and 條 tion2 = 2’

注意: 我用下划线 _替换了空格,因为它们是由编辑器修剪的

选择三

def query():
sql = """select field1, field2, field3, field4
from table
where condition1=1
and condition2=2"""
con = mymodule.get_connection()
...
  • 我不喜欢这个选项,因为它破坏了清晰的表格代码。

选择四

def query():
sql = "select field1, field2, field3, field4 " \
"from table " \
"where condition1=1 " \
"and condition2=2 "
con = mymodule.get_connection()
...
  • 我不喜欢这个选项,因为每行中都有额外的输入 也很难编辑查询。

对我来说,最好的解决方案是 选择二,但是我不喜欢在打印 sql 字符串时多出来的空格。

你还有别的选择吗?

201635 次浏览

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


sql = 'select %s from table where condition1=1 and condition2=2' % (
', '.join(fields))
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
;
>>>

我建议坚持选项2(我总是用它来查询任何比 SELECT * FROM table更复杂的查询) ,如果你想打印它在一个很好的方式,你可以总是使用 独立模块

显然,您已经考虑了很多种方法来编写 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)

如果行的长度超过了需要的长度,那么添加额外的逻辑来将已记录的字符串分成多行也是很容易的。

很抱歉在这么老的帖子上发帖——但是作为一个同样热衷于 Python“最好”的人,我想我应该分享我们的解决方案。

解决方案是使用 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;")

F 弦协同工作:

fields = "field1, field2, field3, field4"
table = "table"
conditions = "condition1=1 AND condition2=2"


sql = (f"SELECT {fields} "
f"FROM {table} "
f"WHERE {conditions};")

优点:

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

对于可以放在一行或两行中的简短查询,我使用上面最受欢迎的解决方案中的字符串文本解决方案。对于较长的查询,我将它们分成 .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 风格指南的启发。

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'"

为了避免 完全格式化,我认为一个很好的解决方案是使用 程序

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

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;

巨蟒

sql =('call example;')

可以使用 inspect.cleandoc对打印的 SQL 语句进行很好的格式化。

这与你的 选择2工作得非常好。

注意: 如果不使用 cleandoc,则 print("-"*40)仅用于演示多余的空行。

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
----------------------------------------

来自 医生:

(文件)

清除文档字符串中的缩进,缩进后的文档字符串将与代码块排成一行。

从第一行删除所有前导空格。任何可以从第二行开始一致删除的前导空格都被删除。随后删除开始和结束处的空行。此外,所有选项卡都展开为空格。

使用‘ sqlparse’库,我们可以格式化 sqls。

>>> 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/

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

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

当您的查询具有诸如“”这样的特殊字符时,建议这样做,因为这需要转义,而 Flake8等 lint 工具将其报告为错误。

谷歌风格指南: https://google.github.io/styleguide/pyguide#310-strings

多行字符串不会随着 如果需要避免在字符串中嵌入额外的空间,请使用 连接的单行字符串或具有 textwrap.dedent()删除每行上的初始空格:

  Yes:
import textwrap


long_string = textwrap.dedent("""\
This is also fine, because textwrap.dedent()
will collapse common leading spaces in each line.""")

字符串可以包围在一对匹配的三重引号中: """'''。 在使用三重引号时,不需要转义行尾,但它们将包含在字符串中。 可以通过在行尾添加 \来防止行尾字符。

下面使用一个转义符来避免不需要的初始空行。

example = """\
SELECT FROM"""

因此,修改了选项2:

import textwrap


def query():
sql = textwrap.dedent("""\
SELECT field1, field2, field3, field4
FROM table
WHERE condition1=1
AND condition2=2""")
con = mymodule.get_connection()
...

返回文章页面 repr(sql):

'SELECT field1, field2, field3, field4\nFROM table\nWHERE condition1=1\nAND condition2=2'

只是分享一个基本用户的字符串格式快手! 在数据科学项目中应该使用哪种 Python 字符串格式化方法?