使用sqlalchemy中的数据库名称限定表名

时间:2012-02-23 16:17:16

标签: python database sqlalchemy

我在多个数据库上使用sqlalchemy和elixir。目前一切都适用于多个会话 - 一个绑定到不同的数据库。但是,有些情况下我想使用一个会话来查询另一个数据库(这是为了支持具有不同复制数据库的多个服务器)。

问题是,当针对一个会话进行查询时,表名不符合正确的数据库名称,我不知道如何告诉查询哪个数据库名称为前缀。有没有办法实现这个目标?

2 个答案:

答案 0 :(得分:2)

使用Oracle作为数据库遇到类似的问题。数据库实例之间的模式名称不同,所以希望这与您的情况类似。

解决此问题的方法是首先向DB发出一个简单查询,以确定架构对象的所有者:

SELECT owner FROM ALL_OBJECTS WHERE object_name = :obj_name AND object_type = :obj_type

然后使用生成的标量作为反射表上schema参数的值:

mytable = Table(name='my_table_name',
                metadata=my_bound_metadata,
                autoload=True,
                schema=schema_owner)

答案 1 :(得分:1)

这可能很难,因为您已经根据不同的绑定绘制了所有内容。 Table的“schema”参数是如何呈现“schemaname.tablename”语法,但是这意味着您将使用与映射到没有模式名称的表的常规映射类不同的映射类。 / p>

首先是一些特定于平台的技术,这将使这更容易。如果您使用的是Oracle,请使用Oracle CREATE SYNONYM将“somedb.sometable”映射到远程模式中的“sometable”。如果您使用的是Postgresql,请操作search_path,以便搜索多个模式以查找给定名称(请参阅http://www.postgresql.org/docs/8.1/static/ddl-schemas.html#DDL-SCHEMAS-PATH)。

这两项工作都没有?那么你需要在http://www.sqlalchemy.org/trac/wiki/UsageRecipes/EntityName这里按照食谱的方式做一些事情(对不起,这不是使用Elixir,我不确定Elixir的功能是什么)。根据具体情况,有不同的方法来实现它。这是一种将新的匿名类映射到原始表的方法:

# regular class
class ClassOne(Base):
    __tablename__ = 'one'
    id = Column(Integer, primary_key=True)

class ClassTwo(Base):
    __tablename__ = 'two'
    id = Column(Integer, primary_key=True)

def map_to_alt_tb(cls, metadata, schemaname):
    m = class_mapper(cls)
    cls2 = type(
        "AltClass",
        (object, ),
        {}
    )
    table = m.local_table.tometadata(metadata, schemaname)
    mapper(cls2, table)
    return cls2

alt_cls = map_to_alt_db(ClassTwo, somemetadata, "alt_schema")

map_to_alt_db()将提取ClassTwo映射到的表,将其架构更改为“alt_schema”,然后将其映射到新类。

这种方法失去了ClassTwo的其他特殊之处。如果您需要,可以在该维基页面上执行更多特定方法。