1. 程式人生 > >SQLAlchemy 執行語句的列印

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