【问题标题】:How can I get Sqlalchemy to preserve column order in the sql it generates?如何让 Sqlalchemy 在它生成的 sql 中保留列顺序?
【发布时间】:2015-05-12 11:03:20
【问题描述】:

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))

【问题讨论】:

    标签: python sqlalchemy


    【解决方案1】:

    列在映射器中的存储方式与在表中的存储方式不同。当你做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' 将“修复”此问题。

    【讨论】:

      【解决方案2】:

      这有点好笑,但是如果您将 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 将转到映射器类的属性参数,该参数将用作可选对象的第一个参数。

      【讨论】:

      • 您能否澄清您正在查看的文件,以及如何修改它以按照声明的顺序获取列?
      • 声明性/base.py 和 orm/mapper.py。更改列的名称 (Column(name=...)) 以匹配属性名称。
      猜你喜欢
      • 2015-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-22
      • 2013-03-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多