我正在使用SQL Alchemy,并且有一些特定于帐户的架构。模式的名称是使用帐户ID派生的,因此在我访问应用程序服务或存储库层之前,我没有模式的名称。我想知道是否可以针对在运行时动态设置其架构的实体运行查询?
我知道我需要设置__table_args__['schema']
并尝试使用内置的type(),但我总是收到以下错误:
could not assemble any primary key columns for mapped table
我已经准备好放弃直接编写sql,但我真的很讨厌这样做。知道如何做到这一点?我正在使用SA 0.99而且我确实有PK映射。
由于
答案 0 :(得分:3)
一种选择是反映特定的帐户相关表。这是关于此事的SqlAlchemy Documentation。
或者,您可以使用静态schema
属性创建表,并在运行时根据需要更新它并运行您需要的查询。我无法想到这样做的非混乱方式。所以这里是凌乱的选项
每当切换帐户时,使用循环更新每个表定义中的架构属性。
将所有特定于帐户的表添加到列表中。
DeclarativeName.__table__.schema
属性。我不确定您是否还需要修改DeclarativeName.__table_args__['schema']
,但我想它不会受到伤害。Table.schema
属性。如果您正在使用任何关系或外键的文本,那么这将会中断,您必须检查每个表格以获取此类硬编码用法并更改它们 示例
user_id = Column(ForeignKey('my_schema.user.id'))
需要写为user_id = Column(ForeignKey(User.id))
。然后,您可以将User
的架构更改为my_new_schema
。否则,在查询时sqlalchemy将会混淆,因为当查询指向my_schema.user.id
时,外键将指向my_new_schema.user
。我不确定在不使用纯文本的情况下是否可以表达更复杂的关系,所以我想这是我提出的解决方案的限制。
这是我在终端写的一个例子:
>>> from sqlalchemy import Column, Table, Integer, String, select, ForeignKey
>>> from sqlalchemy.orm import relationship, backref
>>> from sqlalchemy.ext.declarative import declarative_base
>>> B = declarative_base()
>>>
>>> class User(B):
... __tablename__ = 'user'
... __table_args__ = {'schema': 'first_schema'}
... id = Column(Integer, primary_key=True)
... name = Column(String)
... email = Column(String)
...
>>> class Posts(B):
... __tablename__ = 'posts'
... __table_args__ = {'schema':'first_schema'}
... id = Column(Integer, primary_key=True)
... user_id = Column(ForeignKey(User.id))
... text = Column(String)
...
>>> str(select([User.id, Posts.text]).select_from(User.__table__.join(Posts)))
'SELECT first_schema."user".id, first_schema.posts.text \nFROM first_schema."user" JOIN first_schema.posts ON first_schema."user".id = first_schema.posts.user_id'
>>> account_specific = [User, Posts]
>>> for Tbl in account_specific:
... Tbl.__table__.schema = 'second_schema'
...
>>> str(select([User.id, Posts.text]).select_from(User.__table__.join(Posts)))
'SELECT second_schema."user".id, second_schema.posts.text \nFROM second_schema."user" JOIN second_schema.posts ON second_schema."user".id = second_schema.posts.user_id'
正如您所看到的,在我更新表格的架构属性后,相同的查询引用了second_schema
。
答案 1 :(得分:3)
它们是静态设置的。外键需要相同的处理,我还有一个问题,因为我有多个包含多个表的模式,所以我这样做了:
<a href=#EditContentModal>
然后在我的启动代码中:
from sqlalchemy.ext.declarative import declarative_base
staging_dbase = declarative_base()
model_dbase = declarative_base()
def adjust_schemas(staging, model):
for vv in staging_dbase.metadata.tables.values():
vv.schema = staging
for vv in model_dbase.metadata.tables.values():
vv.schema = model
def all_tables():
return staging_dbase.metadata.tables.union(model_dbase.metadata.tables)
您可以为单个声明性基础修改此内容。
答案 2 :(得分:0)
来自sqlalchemy 1.1, 使用schema_translation_map可以很容易地做到这一点。
答案 3 :(得分:0)
我正在一个项目中,必须在其中动态创建postgres模式和表,然后在适当的模式中插入数据。这是我做过的事,也许会对某人有所帮助:
namespace std_dum
{
int add(int x, int y);
int mult(int x, int y);
}
int main()
{
std::cout << std_dum::add(100, 200) << '\n';
std::cout << std_dum::mult(100, 200) << '\n';
return 0;
}
namespace std_dum
{
int add(int x, int y)
{
return x + y;
}
int mult(int x, int y)
{
return x * y;
}
}