【问题标题】:How to pretty format the printing of SQL Queries in SQLAlchemy?如何在 SQLAlchemy 中漂亮地格式化 SQL 查询的打印?
【发布时间】:2017-11-04 05:35:14
【问题描述】:

我正在使用 SQLAlchemy 使用 compile 并设置 dialectcompile_kwargs 参数(例如,使用 str(ins.compile(dialect=oracle.dialect(), compile_kwargs={'literal_binds': True})))动态生成 PL/SQL 这工作正常,除了输出未格式化有史以来最漂亮的 SQL 语句。

例如,我的一个输出如下所示:

INSERT INTO my_table (a, b, c) SELECT my_table2.d, bar.e, bar.f 
FROM my_table2 JOIN (SELECT my_table3.e AS e, max(my_table3.f) AS f, count(my_table3.g) AS g 
FROM my_table3 
WHERE my_table3.h = 'foo' GROUP BY my_table3.e 
HAVING count(my_table3.g) = 1) bar ON my_table2.g = bar.g

相反,我希望它像下面这样打印出来:

INSERT INTO my _table (a, b c)
SELECT my_table2.d, bar.e, bar.f
FROM my_table2 JOIN (
    SELECT my_table3.e, max(my_table3.f), count(my_table3.g)
    FROM my_table3
    WHERE my_table3.h = 'foo'
    GROUP BY my_table3.e
    HAVING count(my_table3.g) = 1
) bar ON my_table2.g = bar.g

如何让 SQLAlchemy 漂亮地打印 SQL 语句?


复制:

从 sqlalchemy 导入表、列、字符串、数字、函数、选择 从 sqlalchemy.dialects 导入 o​​racle my_table = table('my_table', column('a', String), column('b', String), column('c', String)) my_table2 = table('my_table2', column('d', String), column('g', String)) my_table3 = table('my_table3', column('d', String), column('e', String), column('f', Numeric), column('g', String), column('h',细绳)) inner_sel = select([my_table3.ce, func.max(my_table3.cf).label('f'), func.count(my_table3.cg).label('g')]).where(my_table3.ch== 'foo').group_by(my_table3.ce).having(func.count(my_table3.cg)==1).alias('bar') outer_sel = select([my_table2.c.d, inner_sel.c.e, inner_sel.c.f]).select_from(my_table2.join(inner_sel, my_table2.c.g==inner_sel.c.g)) ins = my_table.insert().from_select([my_table.c.a, my_table.c.b, my_table.c.c], outer_sel) 打印 ins.compile(dialect=oracle.dialect(), compile_kwargs={'literal_binds': True})

【问题讨论】:

  • 我不认为开箱即用。试试sqlparse
  • 它仍在尝试做某事,看起来:它并非全部在 1 行,但在 SQL 关键字之前有一些中断...嗯,我也在为此寻找免费和智能的东西任务。

标签: python oracle python-2.7 sqlalchemy


【解决方案1】:

试试这个猴子补丁:

pip install sqlparse

### monkeypatching SQL'Alchemy for pretty SQL query printing (((
from sqlalchemy.log import InstanceLogger


def pretty_log(self, level, msg, *args, **kwargs):
    if self.logger.manager.disable >= level:
        return

    selected_level = self._echo_map[self.echo]
    if selected_level == logging.NOTSET:
        selected_level = self.logger.getEffectiveLevel()

    if level >= selected_level:

        import sqlparse
        ### HERE IT IS ###
        msg = sqlparse.format(msg, reindent=True, keyword_case='upper')

        self.logger._log(level, '\n'+msg, args, **kwargs)

InstanceLogger.log = pretty_log
### )))

【讨论】:

    【解决方案2】:

    按照@v_retoux 和@olibre 的示例,我在GitHub 上创建了一个易于部署的脚本,该脚本使用sqlparse。它处理一个或多个 sql 文件,并且有一个干净的输出,可以通过管道传输给单个文件。

    这里是来源:

    import argparse, sqlparse, re
    
    parser = argparse.ArgumentParser(prog="sqlpp")
    parser.add_argument("--verbose", "-v", action='store_true')
    parser.add_argument("file", type=argparse.FileType("r"), nargs="+")
    
    args = parser.parse_args()
    
    def prepend(s, s2): return s2 + re.sub('\n', '\n'+s2, s)
    
    # Pretty print input files
    n=len(args.file)
    for i, file in enumerate(args.file):
        sIn = file.read().replace('\n', '')
        file.close()
        sOut = sqlparse.format(sIn, reindent=True, keyword_case='upper')
        if args.verbose or n > 1: 
            print("File{0}:\n    {1}\n{2}\nFormatted SQL:\n{3}\n".format(
                 (' ' + str(i+1) if n > 1 else '')
                ,file.name
                ,("\nOriginal SQL:\n{}\n".format(prepend(sIn, "    ")) 
                        if args.verbose else "")
                ,prepend(sOut, "    ")
            ))
        else:
            print(sOut)
    

    【讨论】:

    • 是的,我对是否添加代码犹豫不决。我现在将输入逻辑的主体。
    【解决方案3】:

    sqlparse 项目已经成熟(10 年以上)并且仍然非常活跃。 sqlparse 旨在解析、拆分和格式化 SQL 语句。

    以下示例使用sqlparse 来漂亮地格式化 SQL 文件:

    import argparse
    import sqlparse
    
    # Parse command line arguments
    parser = argparse.ArgumentParser(prog="pretty_print_sql")
    parser.add_argument("file", type=argparse.FileType("r"), nargs="+")
    args = parser.parse_args()
    
    # Pretty print input files
    for file in args.file:
        print(sqlparse.format(file.read(), reindent=True, keyword_case='upper'))
    

    使用pip安装sqlparse供个人使用:

    python3 -m pip install sqlparse --user --upgrade
    

    使用pipenv 安装sqlparse(在项目中):

    python3 -m pipenv install sqlparse
    

    【讨论】:

      【解决方案4】:

      有几个选项可以尝试:

      【讨论】:

        【解决方案5】:

        你可以使用 sqlparse 包,sqlparse.format(sql, reindent=True, keyword_case='upper') 应该做你想做的事?

        【讨论】:

        • 很好的例子。谢谢。
        猜你喜欢
        • 2018-03-07
        • 2011-01-07
        • 1970-01-01
        • 2017-09-16
        • 2012-05-04
        • 2022-11-18
        • 1970-01-01
        • 2011-05-06
        • 1970-01-01
        相关资源
        最近更新 更多