2010-07-21 61 views
4

我正在嘗試使用SqlAlchemy(0.5.8)以聲明方式與舊數據庫進行接口並使用反射。我的測試代碼如下所示:在SqlAlchemy中反映數據庫時缺少外鍵關係

from sqlalchemy import * 
from sqlalchemy.orm import create_session 
from sqlalchemy.ext.declarative import declarative_base 

Base = declarative_base() 
engine = create_engine('oracle://schemaname:[email protected]') 
meta = MetaData(bind=engine) 

class CONSTRUCT(Base): 
    __table__ = Table('CONSTRUCT', meta, autoload=True) 

class EXPRESSION(Base): 
    __table__ = Table('EXPRESSION', meta, autoload=True) 

session = create_session(bind=engine) 

現在,當我嘗試使用這兩個表(由外鍵約束在底層Oracle架構中定義)之間的連接運行查詢:

print session.query(EXPRESSION).join(PURIFICATION) 

...沒有喜悅:

sqlalchemy.exc.ArgumentError: Can't find any foreign key relationships between 'EXPRESSION' and 'PURIFICATION' 

但是:

>>> EXPRESSION.epiconstruct_pkey.property.columns 
[Column(u'epiconstruct_pkey', OracleNumeric(precision=10, scale=2, asdecimal=True, 
length=None), ForeignKey(u'construct.pkey'), table=<EXPRESSION>, nullable=False)] 

>>> CONSTRUCT.pkey.property.columns 
[Column(u'pkey', OracleNumeric(precision=38, scale=0, asdecimal=True, length=None), 
table=<CONSTRUCT>, primary_key=True, nullable=False)] 

這清楚地表明反射拾取了外鍵。

我哪裏錯了?

回答

5

用Eclipse調試腳本+ SqlAlchemy代碼後,我發現表/列的列表內部保持小寫。因此,EXPRESSION.foreignkey和expression.foreignkey之間絕無可能匹配。因此錯誤信息。

深挖入SQLAlchemy的文檔(http://www.sqlalchemy.org/docs/reference/dialects/oracle.html#identifier-casing)我然後發現如下:

「在Oracle,使用大寫文本數據字典代表所有不區分大小寫的標識符名稱的SQLAlchemy另一方面認爲全低。案例標識符名稱不區分大小寫Oracle模式在模式級通信期間將所有不區分大小寫的標識符轉換爲或來自這兩種格式,例如表和索引的反映。在SQLAlchemy側使用大寫名稱表示區分大小寫的標識符,以及SQLAlchemy會引用名稱 - 這將導致與從Oracle收到的數據字典數據不匹配,所以除非標識符名稱已真正創建爲區分大小寫(即usi ng引用的名稱),所有小寫名稱都應該用在SQLAlchemy方面。「

所以我的代碼工作,如果它看起來像這樣(的差別僅僅是個案的變化):

from sqlalchemy import * 
from sqlalchemy.orm import create_session 
from sqlalchemy.ext.declarative import declarative_base 

Base = declarative_base() 
engine = create_engine('oracle://EPIGENETICS:[email protected]') 
meta = MetaData(bind=engine) 

class construct(Base): 
    __table__ = Table('construct', meta, autoload=True) 

class expression(Base): 
    __table__ = Table('expression', meta, autoload=True) 

class purification(Base): 
    __table__ = Table('purification', meta, autoload=True) 

session = create_session(bind=engine) 
print session.query(expression).join(purification,expression) 

...它吐出:

SELECT expression.pkey AS expression_pkey, expression.cellline AS expression_cellline, expression.epiconstruct_pkey AS expression_epiconstruct_pkey, expression.elnexp AS expression_elnexp, expression.expression_id AS expression_expression_id, expression.expressioncomments AS expression_expressioncomments, expression.cellmass AS expression_cellmass, expression.datestamp AS expression_datestamp, expression.person AS expression_person, expression.soluble AS expression_soluble, expression.semet AS expression_semet, expression.scale AS expression_scale, expression.purtest AS expression_purtest, expression.nmrlabelled AS expression_nmrlabelled, expression.yield AS expression_yield 
FROM expression JOIN purification ON expression.pkey = purification.epiexpression_pkey JOIN expression ON expression.pkey = purification.epiexpression_pkey 

結案。