Python 如何在SQLAlchemy中设置SQL查询打印的格式?
我正在使用SQLAlchemy动态生成PL/SQL,使用compile并设置方言和compile_-kwargs参数,例如,使用strins.compiledialect=oracle.dialect,compile_-kwargs={'literal_-binds':True}这很好,但输出的格式并不是有史以来最漂亮的SQL语句 例如,我的一个输出如下所示:Python 如何在SQLAlchemy中设置SQL查询打印的格式?,python,oracle,python-2.7,sqlalchemy,Python,Oracle,Python 2.7,Sqlalchemy,我正在使用SQLAlchemy动态生成PL/SQL,使用compile并设置方言和compile_-kwargs参数,例如,使用strins.compiledialect=oracle.dialect,compile_-kwargs={'literal_-binds':True}这很好,但输出的格式并不是有史以来最漂亮的SQL语句 例如,我的一个输出如下所示: INSERT INTO my_table (a, b, c) SELECT my_table2.d, bar.e, bar.f FRO
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语句
复制:
from sqlalchemy import table, column, String, Numeric, func, select
from sqlalchemy.dialects import oracle
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', String))
inner_sel = select([my_table3.c.e, func.max(my_table3.c.f).label('f'), func.count(my_table3.c.g).label('g')]).where(my_table3.c.h=='foo').group_by(my_table3.c.e).having(func.count(my_table3.c.g)==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)
print ins.compile(dialect=oracle.dialect(), compile_kwargs={'literal_binds': True})
您可以使用sqlparse包和sqlparse.formatsql,reindent=True,关键字\u case='upper'应该做您想做的事?有几个选项可以尝试: 该项目已成熟10多年,目前仍非常活跃。sqlparse旨在解析、拆分和格式化SQL语句 以下示例使用sqlparse对SQL文件进行精确格式化: 导入argparse 导入sqlparse 解析命令行参数 parser=argparse.ArgumentParserprog=pretty\u print\u sql parser.add_argumentfile,type=argparse.FileTyper,nargs=+ args=parser.parse_args 漂亮的打印输入文件 对于args.file中的文件: printsqlparse.formatfile.read,reindent=True,关键字\u case='upper' 要使用pip安装sqlparse供个人使用,请执行以下操作:
python3 -m pip install sqlparse --user --upgrade
要在项目中使用pipenv安装sqlparse,请执行以下操作:
python3 -m pipenv install sqlparse
在@v_retoux和@olibre的示例之后,我创建了一个易于部署的脚本,该脚本使用。它处理一个或多个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)
试试这个猴子补丁:
pip安装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
### )))