您是否曾经发现如果在 session.query()之后放置 commit(),则会对查询中的每一行单独执行SQL,SQLAlchemy 忽略模型定义中的lazy ='joined':
ENGINE = create_engine("mysql+pymysql://........")
SESS = sessionmaker(bind=ENGINE)
session = SESS()
try:
session.query(Document).order_by(desc('number'))[0:5]
session.commit()
except:
session.rollback()
raise
模型与往常一样:
class Document(BASE):
""" Document mapping """
__tablename__ = "document"
id = Column(Integer, primary_key=True)
number = Column(String)
currency_id = Column(Integer, ForeignKey('currency.id'))
currency = relationship("Currency", lazy='joined')
class Currency(BASE):
""" Currency mapping """
__tablename__ = "currency"
label = Column(String)
id = Column(Integer, primary_key=True)
没有 session.commit() SQL是:
70306 10:32:52 149 Connect venice@localhost as anonymous on venice
149 Query SET AUTOCOMMIT = 0
149 Query SELECT document.id AS document_id, document.number AS document_number, document.currency_id AS document_currency_id, currency_1.label AS currency_1_label, currency_1.created_at AS currency_1_created_at, currency_1.updated_at AS currency_1_updated_at, currency_1.id AS currency_1_id
FROM document LEFT OUTER JOIN currency AS currency_1 ON currency_1.id = document.currency_id ORDER BY document.number ASC
LIMIT 5
但是 session.commit() SQL是:
170306 10:31:58 147 Connect venice@localhost as anonymous on venice
147 Query SET AUTOCOMMIT = 0
147 Query SELECT document.id AS document_id, document.number AS document_number, document.currency_id AS document_currency_id, currency_1.label AS currency_1_label, currency_1.created_at AS currency_1_created_at, currency_1.updated_at AS currency_1_updated_at, currency_1.id AS currency_1_id
FROM document LEFT OUTER JOIN currency AS currency_1 ON currency_1.id = document.currency_id ORDER BY document.number ASC
LIMIT 5
147 Query COMMIT
147 Query ROLLBACK
147 Query SELECT document.id AS document_id, document.number AS document_number, document.currency_id AS document_currency_id
FROM document
WHERE document.id = 4357
147 Query SELECT currency.label AS currency_label, currency.created_at AS currency_created_at, currency.updated_at AS currency_updated_at, currency.id AS currency_id
FROM currency
WHERE currency.id = 1
147 Query SELECT document.id AS document_id, document.number AS document_number, document.currency_id AS document_currency_id
FROM document
WHERE document.id = 293
147 Query SELECT document.id AS document_id, document.number AS document_number, document.currency_id AS document_currency_id
FROM document
WHERE document.id = 569
147 Query SELECT document.id AS document_id, document.number AS document_number, document.currency_id AS document_currency_id
FROM document
WHERE document.id = 6521
147 Query SELECT document.id AS document_id, document.number AS document_number, document.currency_id AS document_currency_id
FROM document
WHERE document.id = 7614
当生成异常时,例如欺骗场造成的:
documents = session \
.query(Document) \
.order_by(asc("bad_field"))[0:20]
然后python输出:
InternalError: (pymysql.err.InternalError) (1054, u"Unknown column 'bad_field' in 'order clause'") [SQL: u'SELECT document.id AS document_id, document.number AS document_number, document.currency_id AS document_currency_id, currency_1.label AS currency_1_label, currency_1.created_at AS currency_1_created_at, currency_1.updated_at AS currency_1_updated_at, currency_1.id AS currency_1_id \nFROM document LEFT OUTER JOIN currency AS currency_1 ON currency_1.id = document.currency_id ORDER BY bad_field ASC \n LIMIT %(param_1)s'] [parameters: {u'param_1': 20}]
和MariaDB日志:
170306 23:29:09 195 Connect venice@localhost as anonymous on venice
195 Query SET AUTOCOMMIT = 0
195 Query SHOW VARIABLES LIKE 'sql_mode'
195 Query SELECT DATABASE()
195 Query SELECT @@tx_isolation
195 Query show collation where `Charset` = 'utf8' and `Collation` = 'utf8_bin'
195 Query SELECT CAST('test plain returns' AS CHAR(60)) AS anon_1
195 Query SELECT CAST('test unicode returns' AS CHAR(60)) AS anon_1
195 Query SELECT CAST('test collated returns' AS CHAR CHARACTER SET utf8) COLLATE utf8_bin AS anon_1
195 Query ROLLBACK
195 Query SELECT document.id AS document_id, document.number AS document_number, document.currency_id AS document_currency_id, currency_1.label AS currency_1_label, currency_1.created_at AS currency_1_created_at, currency_1.updated_at AS currency_1_updated_at, currency_1.id AS currency_1_id FROM document LEFT OUTER JOIN currency AS currency_1 ON currency_1.id = document.currency_id ORDER BY bad_field ASC LIMIT 20
195 Query ROLLBACK
195 Query ROLLBACK