2017-09-18 3 views
1

J'ai lutté sur cela pendant un certain temps maintenant et n'a pas encore trouvé de réponse, ou peut-être que j'ai déjà vu la réponse et je n'ai pas compris - cependant, je J'espère que je suis capable de décrire mon problème.sqlalchemy carte table de base de données mssql avec "prefix-namespaces"

J'ai une base de données MS SQL dans laquelle les tables sont groupées dans des espaces de noms (ou quel que soit son nom), notés Prefix.Tablename (avec un point). Donc, une instruction SQL native pour demander du contenu ressemble à ceci:

SELECT TOP 100 
    [Value], [ValueDate] 
    FROM [FinancialDataBase].[Reporting].[IndexedElements] 

Comment faire correspondre cela à sqlalchemy? Si le préfixe « Reporting » ne serait pas là, la solution (ou une façon de le faire) ressemble à ceci:

from sqlalchemy import * 
from sqlalchemy.ext.declarative import declarative_base, declared_attr 
from sqlalchemy.orm import sessionmaker 

def get_session(): 
    from urllib.parse import quote_plus as urllib_quote_plus 

    server = "FinancialDataBase.sql.local" 
    connstr = "DRIVER={SQL Server};SERVER=%s;DATABASE=FinancialDataBase" % server 
    params = urllib_quote_plus(connstr) 
    base_url = "mssql+pyodbc:///?odbc_connect=%s" % params 

    engine = create_engine(base_url,echo=True) 
    Session = sessionmaker(bind=engine) 
    session = Session() 

    return engine, session 

Base = declarative_base() 

class IndexedElements(Base): 
    __tablename__ = "IndexedElements" 

    UniqueID = Column(String,primary_key=True) 
    ValueDate = Column(DateTime) 
    Value = Column(Float) 

Et puis les demandes peuvent être faites et enveloppé dans un dataframe Pandas par exemple comme ceci:

import pandas as pd 

engine, session = get_session() 

query = session.query(IndexedElements.Value,IndexedElements.ValueDate) 

data = pd.read_sql(query.statement,query.session.bind) 

Mais l'instruction SQL qui est compilé et exécuté en fait dans ce domaine, comprend cette mauvaise clause FROM:

FROM [FinancialDataBase].[IndexedElements] 

en raison de l'espace de noms préfixe il wo ULD doivent être

FROM [FinancialDataBase].[Reporting].[IndexedElements] 

expansion simplement le nom de la table

__tablename__ = "Reporting.IndexedElements" 

ne marche pas fixer, car il modifie l'instruction SQL compilé

FROM [FinancialDataBase].[Reporting.IndexedElements] 

qui ne marche pas le travail correctement.

Alors, comment cela peut-il être résolu?

+0

Le terme que vous recherchez est [schéma] (https://technet.microsoft.com/fr-fr/library/dd283095 (v = sql. 100) .aspx). SQLAlchemy prend en charge les schémas à la fois dans les [métadonnées] (http://docs.sqlalchemy.org/en/latest/core/metadata.html#sqlalchemy.schema.MetaData.params.schema) en tant que schéma par défaut à utiliser et [par table ] (http://docs.sqlalchemy.org/en/latest/core/metadata.html#sqlalchemy.schema.Table.params.schema). Avec Declarative vous devez passer un schéma par table dans ['__table_args__'] (http://docs.sqlalchemy.org/en/latest/orm/extensions/declarative/table_config.html#table-configuration). –

+0

Très lié: https://stackoverflow.com/questions/30538132/sqlalchemy-declarative-schemas-in-sql-server-and-foreign-primary-keys –

+0

Merci Ilja, "schéma" cloué! Je vais créer une réponse en référence à votre commentaire! – joaquinn

Répondre

2

La réponse est donnée dans le commentaire par Ilja ci-dessus:

Le « espace de noms » est un soi-disant schéma et doit être declarated dans l'objet mappé. Étant donné l'exemple du poste d'ouverture, la table mappée doit être défini comme ceci:

class IndexedElements(Base): 
    __tablename__ = "IndexedElements" 
    __table_args__ = {"schema": "Reporting"} 

    UniqueID = Column(String,primary_key=True) 
    ValueDate = Column(DateTime) 
    Value = Column(Float) 

Ou définir une classe de base contenant ces informations pour différents schèmes. Vérifiez également "Augmenting the base" dans sqlalchemy docs: http://docs.sqlalchemy.org/en/latest/orm/extensions/declarative/mixins.html#augmenting-the-base