9

I have data for a particular entity partitioned across multiple identical tables, often separated chronologically or by numeric range. For instance, I may have a table called mytable for current data, a mytable_2013 for last year's data, mytable_2012, and so on.

Only the current table is ever written to. The others are only consulted. With SQLAlchemy, is there any way I can specify the table to query from when using the declarative model?

asked Aug 22, 2014 at 16:12
6
  • Please take a look at stackoverflow.com/a/22825638/99594 in the Concrete Table Inheritance section. I would not like to re-post it as an answer, as it is quite long. In your case you can query MyTable only when working with the current data, and do a polymorphic search when looking for all the history. Commented Aug 26, 2014 at 18:39
  • Thanks. My case is more simple it's the same entity distributed horizontally, not multiple entities defined by inheritance. Considering that, it seems to be the same solution as the one by @viktor.likin answer below. Commented Aug 26, 2014 at 19:42
  • Inheritance is just a trick to get SA to query across multiple tables. But if you do not need that, viktor's solution is perfect. Note that if you have foreign keys from your table(s), you will need to use declared_attr Commented Aug 26, 2014 at 20:28
  • Yeah, I just stumbled on that. Can you clarify the point about inheritance being just a trick to get SA to query across multiple tables. Does that work with the horizontal partitioning I'm doing? SQLAlchemy does an UNION automatically? Commented Aug 26, 2014 at 20:45
  • Yes, it can work with the horizontal partitioning you are doing. The trick is to query all (or some of) the (fake) inheritance tree polymorphically. This is to say: if you make SA think that all those tables are "children" of MyBaseTable, and you execute a query polymorphically, SA will fetch data from all these tables (mytable, mytable_2012, etc) automatically for you. Indeed, SA does a UNION automatically. Commented Aug 27, 2014 at 6:51

3 Answers 3

12

Use mixins and change table names by an object property.

class Node(Base):
 __tablename__ = 'node'
 nid = Column(Integer, primary_key=True)
 uuid = Column(String(128))
 vid = Column(Integer)
class Node1(Node):
 __tablename__ = 'node_1'
class Node2(Node):
 __tablename__ = 'node_2'
answered Aug 26, 2014 at 14:36
Sign up to request clarification or add additional context in comments.

This method is less complicated than the accepted answer. Here is a link to a recipe that uses a similar approach: bitbucket.org/zzzeek/sqlalchemy/wiki/UsageRecipes/EntityName
not working anymore, produces NoForeignKeysError("Can't find any foreign key relationships between 'Node and 'Node1'.",)
The answer is correct, the code is not (or not anymore ;-)). Define the mixin by a) replicating the Node-class as class NodeMixin(object): followed by the column definitions of the Node-class but without the __table_name__-property and b) for Node1 and Node2 inherit from the mixin and Base, e. g. class Node1(NodeMixin, Base): __tablename__ = "node_1". See: docs.sqlalchemy.org/en/14/orm/…
5
+50

As requested, re-posting as answer:

Please take a look at this answer to Mapping lots of similar tables in SQLAlchemy in the Concrete Table Inheritance section.
In your case you can query MyTable only when working with the current data, and do a polymorphic search on all tables when you need the whole history.

augurar
13.4k7 gold badges60 silver badges71 bronze badges
answered Aug 27, 2014 at 16:47

Comments

2

Update for SQLAlchemy 2.0

The syntax changed slightly. Most importantly, the mixin-class does not inherit from Base anymore (SQLAlchemy 2.0).

class MultiTableMixin:
 id: Mapped[int] = mapped_column(primary_key=True)
 name: Mapped[Optional[str]]
class MyModel(MultiTableMixin, Base):
 __tablename__ = "table1"
class MyModel(MultiTableMixin, Base):
 __tablename__ = "table2"
answered Jul 5, 2024 at 15:06

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.