2012-02-23 82 views
2

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

问题是,当针对一个会话进行查询时,表名未使用正确的数据库名称限定,我不知道如何告诉查询要将哪个数据库名称作为前缀。有什么办法可以做到这一点?

回答

1

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

因此,首先是一些特定于平台的技术,这将使这一过程变得更加简单。如果您使用的是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的能力是如何)。取决于具体情况,有不同的方法来实现它。这里有一种方法,这将使映射到原来的表一个新的,匿名类:

# 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。如果你需要的话,你可以在Wiki页面上做更多的特定方法。

2

与Oracle遇到了与DB类似的问题。数据库实例之间的模式名称不同,因此希望这与您的情况类似。

的方法来解决,这是最初触发一个简单的查询到数据库,以确定该模式对象的所有者:

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

然后用所得的标量作为对您反映的模式参数的值表格:

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