Я новичок в sqlalchemy и python ORM, поэтому, если я здесь что-то не так, пожалуйста, дайте мне знать.
У меня есть база данных с несколькими таблицами (более 4 в большинстве), и я хочу, чтобы все они были в одном классе. Из того, что я прочитал, я могу создать классы для каждой таблицы базы данных и сделать sqlacademy запросом __table__
для класса. Другой основной вариант, который я могу найти, - создать представление / запрос sql и просто отобразить это как одну «таблицу». Каждая из моих таблиц имеет отношение 1: 1.
Существует ли способ объединения нескольких (3+) таблиц для создания одного класса? Что-то вроде:
from sqlalchemy import MetaData, Table, Column, Integer, ForeignKey, join
from sqlalchemy.ext.declarative import declarative_base
metadata = MetaData()
a = Table('table_a', metadata,
Column('id', Integer, primary_key=True)
)
b = Table('table_b', metadata,
Column('id', Integer, ForeignKey('table_a.id'), primary_key=True)
)
c = Table('table_c', metadata,
Column('c_id', Integer, ForeignKey('table_a.id'), primary_key=True)
)
Base = declarative_base()
busObj = join(a, b, c)
#busObj = join(a, b).join(c) # as an alternative
class BusinessObj(Base):
__table__ = busObj
def __repr__(self):
return "BusinessObj {}".format(self.id)
Когда я пытаюсь выполнить вышеизложенное, я получаю следующую ошибку:
Traceback (most recent call last):
File "$PYTHON_APP_DATA\site-packages\sqlalchemy\engine\base.py", line 1244, in _execute_context
cursor, statement, parameters, context
File "$PYTHON_APP_DATA\site-packages\sqlalchemy\engine\default.py", line 550, in do_execute
cursor.execute(statement, parameters)
cx_Oracle.DatabaseError: ORA-00936: missing expression
SQL, который он генерирует, verbaitim:
SELECT "table_a".id AS "table_a_id",
"table_b".id AS "table_b_id",
"table_c".user_id AS "table_c_user_id"
FROM "table_c",
"table_a"
JOIN "table_b" ON
Из приведенного выше видно, что проблема заключается в том, что он не объединяет table_a и table_b ни в каких полях и даже не думает о присоединении table_c вообще.
РЕДАКТИРОВАТЬ 2: Этот вопрос был сформулирован плохо ине точно отражает проблемы, с которыми я столкнулся. Я закрою этот пост, но чтобы ответить на плохо сформулированный вопрос, который у меня был выше, на случай, если другая потерянная душа наткнется на это:
Правильный синтаксис для того, что я искал, был
busObj = join(table_a, table_b, onclause=table_a.c.id==table_b.c.id)\
.join(table_c, onclause=table_a.c.id==table_c.c.user_id)
Однако при этом я столкнулся с ошибкой, потому что у меня была рекурсивная ссылка на таблицу. Бизнес-объект, с которым я работаю, это Users
, который также имеет поле created_by
, которое ссылается на идентификатор пользователя, создавшего эту первую учетную запись. Вы можете увидеть проблему.
На данный момент вышеприведенное работает, с обходным решением, не включающим часть внешнего ключа поля create_by - но мне придется вручную обновить это поле позже, если / когда это поле потребуетсяподлежит обновлению.