Отношения внешнего ключа отсутствуют при отражении БД в SqlAlchemy - PullRequest
4 голосов
/ 21 июля 2010

Я пытаюсь использовать 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)]

Что явно указывает на то, что отражение подхватило внешний ключ.

Куда я иду не так?

1 Ответ

5 голосов
/ 21 июля 2010

После отладки скрипта + кода SqlAlchemy с помощью Eclipse я обнаружил, что список таблиц / столбцов хранится внутри в нижнем регистре. Таким образом, никогда не было возможности совпадения между EXPRESSION.foreignkey и expression.foreignkey. Отсюда и сообщение об ошибке.

Углубившись в документацию по SqlAlchemy (http://www.sqlalchemy.org/docs/reference/dialects/oracle.html#identifier-casing), я обнаружил следующее:

"В Oracle словарь данных представляет все имена символов, нечувствительные к регистру, используя текст UPPERCASE. С другой стороны, SQLAlchemy считает, что имя идентификатора всех строчных букв нечувствительно к регистру. Диалект Oracle преобразует все идентификаторы, не чувствительные к регистру, в и из них. два формата во время обмена данными на уровне схемы, такие как отображение таблиц и индексов. Использование имени UPPERCASE на стороне 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

Дело закрыто.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...