【问题标题】:SQLite and Postgres Partial index support with inherited parameter using SQLAlchemy使用 SQLAlchemy 继承参数的 SQLite 和 Postgres 部分索引支持
【发布时间】:2020-11-04 12:40:22
【问题描述】:

我正在尝试创建一个具有以下独特组合的表: 只有一个条目的account_id 设置为active,但同一account_id 的多个条目其中active 设置为False,这意味着这是一种可能性:

id |  account_id  | active | timestamp
0  |  12          |  False | 2020-07-15 04:10:48.380781
1  |  12          |  True  | 2020-07-15 04:10:48.380781
2  |  12          |  False |2020-07-15 04:10:48.380781

但这不能:

id |  account_id  | active | timestamp
0  |  12          |  False |2020-07-15 04:10:48.380781
1  |  12          |  True  |2020-07-15 04:10:48.380781
2  |  12          |  True  |2020-07-15 04:10:48.380781

我打算使用部分索引来获得此功能,但需要注意的是 account_idactive 都是从泛型类继承的。这些类如下所示:

class GenericClass:
    id = Column(Integer, primary_key=True)
    active = Column(Boolean, nullable=False,
                    doc='Whether this is active or not.'
    @declared_attr        # declared_attr decorator makes it like classmethod
    def account_id(cls):
        return Column(Integer, ForeignKey('account.account_id'))

这是我的实际表格:

class AdvancedTable(Some.Model, GenericClass):
    __versioned__ = {}
    __table_args__ = ( 
        Index('active_accid_index', 'account_id',
              unique=True,
              sqlite_where= GenericClass.active,
              postgresql_where= GenericClass.active),
        )
    timestamp = Column(
        DateTime, nullable=True, doc='DateTime this info was activated.')

但我收到以下错误: sqlalchemy.exc.CompileError: Cannot compile Column object until its 'name' is assigned.

谁能帮我实现我想要的功能而无需获得GenericClass,(我同时使用 postgresql 和 sqlite)?

【问题讨论】:

  • 我删除了不一致的数据库标签。请仅使用您真正使用的数据库进行标记 - 或者如果您使用多个数据库,请在问题中明确。
  • 我同时使用 Postgresql 和 sqlite,在表类中我有两个数据库 where 语句。
  • 什么是“Some.Model”?
  • Some.Model 是基类
  • 您能否在“活动”列上创建一个“更新前”触发器。

标签: python sql postgresql sqlite sqlalchemy


【解决方案1】:

我相信我通过将索引移到表定义之外来解决了这个问题。请参阅下面的代码。突出显示相关部分。

Base = declarative_base()

class GenericClass(object):
    @declared_attr
    def account_id(cls):
        return Column('account_id', ForeignKey('account.id'))

    @declared_attr
    def account(cls):
        return relationship("Account")

    active = Column(Boolean, nullable=False, doc='Whether this is active or not.') 

class Account(Base):
    __tablename__ = 'account'
    id = Column(Integer, primary_key=True)
    name = String(length=32)

class AdvancedTable(GenericClass, Base):
    __versioned__ = {}
    __tablename__ = "advanced"
    id = Column(Integer, primary_key=True)

    timestamp = Column(
        DateTime, nullable=True, doc='DateTime this info was activated.')

my_index = Index('active_accid_index', AdvancedTable.account_id, unique = True, 
                 sqlite_where = AdvancedTable.active )
# ===== This is the key part =====

engine = create_engine('sqlite:///advanced.db')
Base.metadata.create_all(engine)

对于 sqlite,生成的架构是:

CREATE TABLE account (
    id INTEGER NOT NULL, 
    PRIMARY KEY (id)
);
CREATE TABLE advanced (
    active BOOLEAN NOT NULL, 
    id INTEGER NOT NULL, 
    timestamp DATETIME, 
    account_id INTEGER, 
    PRIMARY KEY (id), 
    CHECK (active IN (0, 1)), 
    FOREIGN KEY(account_id) REFERENCES account (id)
);
CREATE UNIQUE INDEX active_accid_index ON advanced (account_id) WHERE active;

【讨论】:

  • 这能回答你的问题吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-03-14
  • 2012-03-07
  • 1970-01-01
  • 2011-03-22
  • 2011-09-25
  • 2012-09-06
相关资源
最近更新 更多