python - 在 SqlAlchemy 中反射(reflect)数据库时缺少外键关系

标签 python oracle10g sqlalchemy

我正在尝试使用 SqlAlchemy (0.5.8) 以声明方式与遗留数据库交互并使用反射。我的测试代码如下所示:

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

Base = declarative_base()
engine = create_engine('oracle://schemaname:pwd@SID')
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)]

这清楚地表明反射拾取了外键。

我哪里错了?

最佳答案

在使用 Eclipse 调试脚本 + SqlAlchemy 代码后,我发现表/列列表在内部以小写形式保存。因此,EXPRESSION.foreignkey 和 expression.foreignkey 之间永远不可能匹配。因此出现错误消息。

深入研究 SqlAlchemy 文档 ( http://www.sqlalchemy.org/docs/reference/dialects/oracle.html#identifier-casing ) 然后我发现了以下内容:

“在 Oracle 中,数据字典使用大写文本表示所有不区分大小写的标识符名称。另一方面,SQLAlchemy 认为全小写的标识符名称不区分大小写。Oracle 方言将所有不区分大小写的标识符与那些不区分大小写的标识符相互转换模式级别通信期间的两种格式,例如表和索引的反射。在 SQLAlchemy 端使用大写名称表示区分大小写的标识符,SQLAlchemy 将引用该名称 - 这将导致与从 Oracle 接收的数据字典数据不匹配,因此除非标识符名称已真正创建为区分大小写(即使用带引号的名称),所有小写名称都应在 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:sgc04lab@ELN')
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

结案。

关于python - 在 SqlAlchemy 中反射(reflect)数据库时缺少外键关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3301139/

相关文章:

python - scipy.stats.binom 库可以为特定的 "N"和 "k"返回值 "p"

sql - 如何识别存储在 Oracle DATE 列中的无效(损坏)值

python - 唯一增量及其表宽最大值 + 1

python - 使用 SQLAlchemy 在 PostgreSQL 中创建函数和触发器

python - 在 python 中计算不带 '*' 符号的(几乎代数)表达式

python - 如何读取所有图像的形状并显示它们,并通过 google colab 显示在数据集文件夹中?

python - JSON解码错误 : Unexpected UTF-8 BOM: Display problems in bash?

sql - 如何在 Oracle 10g 中解析相邻列表?

oracle - 如何调用 Oracle PL/SQL 对象 super 方法

python - flask many to many join 由 django 的 prefetch_related 完成