如何让Sqlalchemy保留它生成的sql中的列顺序?

时间:2015-03-10 20:22:07

标签: python sqlalchemy

Sqlalchemy在为表生成sql时似乎没有保留列顺序。如何让sqlalchemy使用与定义列相同的顺序?

示例:

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Table, MetaData, Column, BigInteger, Integer, String, MetaData, ForeignKey, Date, DateTime

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
Base = declarative_base()


class MyTable(Base):
    __tablename__ = "my_table"

    id = Column(BigInteger, primary_key=True)
    col1 = Column(String(20), name="col1")
    col2 = Column(Integer)
    col3 = Column(BigInteger, name="col_3")

engine = create_engine('sqlite:///foo.db')
Session = sessionmaker(engine)
db = Session()

print(db.query(MyTable).statement.compile(engine))

输出是:

SELECT my_table.col_3, my_table.id, my_table.col1, my_table.col2
FROM my_table

而不是

SELECT my_table.id, my_table.col1, my_table.col2, my_table.col_3
FROM my_table

Sqlalchemy似乎确实保留了表定义中的列顺序,因为当它生成CREATE TABLE命令时,列顺序与订单列匹配。

from sqlalchemy.schema import CreateTable
print(CreateTable(MyTable.__table__).compile(engine))

2 个答案:

答案 0 :(得分:2)

列在mapper中的存储方式与表中的不同。当您执行CreateTable(MyTable.__table__) looks through columns on the table时。当您执行session.query(MyTable) looks through _props on the current mapper时。 _props的填充方式与columns的填充方式不同,由于SQLAlchemy内部的某些决定,这可能会导致不同的顺序。

答案最终是否定的,你不能保证查询列的顺序,因为幕后工作还有其他的力量。如果命令对你很重要,那么它应该是brought up as an issue对抗SQLAlchemy。

在这种情况下,指定与属性名称不匹配的列名会更改列内部存储的顺序。从该列中删除name='col_3'将"修复"此

答案 1 :(得分:1)

这有点好笑,但如果你将col_3更改为col3,它会按声明的方式发出列。

为什么?

执行映射器配置时,会有此注释

        # look through columns in the current mapper that
        # are keyed to a propname different than the colname
        # (if names were the same, we'd have popped it out above,
        # in which case the mapper makes this combination).
        # See if the superclass has a similar column property.
        # If so, join them together.

你的col_3将转到mapper类的属性参数,该参数将用作可选择的第一个参数。