SQLAlchemy 執行語句的列印
最近需要分析業務程式碼中MySQL語句執行效率,對於直接顯示執行SQL語句的地方,可以直接將SQL語句和引數拼接後的結果打印出來,但是對於用SQLAlchemy Query查詢的地方,就需要想辦法打印出最後實際執行的語句。找了下各種方案,最後結果如下:
方式一:
SQLAlchemy支援在建立資料庫引擎時,通過echo=true,將連線這個資料庫引擎的所有執行語句打印出來:
engine = create_engine("<db_rul>", echo=True)
這種方式會自動將連線資料庫過程中的所有型別語句,以及這些語句的引數列表打印出來。也即是說,這種方式打印出的語句和語句中的引數是分離的。
方式二:
query = session.query(Model).filter(*query_cond).order_by(order_info)
對於某一個像上邊這樣的查詢或插入語句,可以直接通過下邊的方式,打印出不包含引數的SQL語句
print str(query)
這種方式得到的SQL也不可直接執行,因為對應的引數變數沒有被替換
方式三
from sqlalchemy.dialects import mysql
print str(query.statement.compile(dialect=mysql.dialect(), compile_kwargs={"literal_binds": True}))
這種方式可以列印包含引數的執行語句,但是引數只包括數字和字串等基本型別。其中dialects表示需要的資料庫方言,我這裡用的mysql。
基於方式三,增加部分程式碼,來列印datetime等型別的引數。
from sqlalchemy.orm import Query from datetime import date, timedelta
def render_query(statement, dialect=None): query = session.query(Model).filter(*query_cond) print render_query(query) result = query.all() """ if isinstance(statement, Query): if dialect is None: dialect = statement.session.bind.dialect statement = statement.statement elif dialect is None: dialect = statement.bind.dialect
class LiteralCompiler(dialect.statement_compiler):
def visit_bindparam(self, bindparam, within_columns_clause=False, literal_binds=False, **kwargs): return self.render_literal_value(bindparam.value, bindparam.type)
def render_array_value(self, val, item_type): if isinstance(val, list): return "{%s}" % ",".join([self.render_array_value(x, item_type) for x in val]) return self.render_literal_value(val, item_type)
def render_literal_value(self, value, type_): if isinstance(value, long): return str(value) elif isinstance(value, (basestring, date, datetime.datetime, timedelta)): return "'%s'" % str(value).replace("'", "''") elif isinstance(value, list): return "'{%s}'" % (",".join([self.render_array_value(x, type_.item_type) for x in value])) return super(LiteralCompiler, self).render_literal_value(value, type_)
return LiteralCompiler(dialect, statement).process(statement)
參考:
http://stackoverflow.com/questions/5631078/sqlalchemy-print-the-actual-query