0

我有来自我的客户的 MS Access DB 文件 (.accdb),需要用 declarative_base 类描述表和列。正如我在表构造函数中看到的那样 - 其中一个列具有整数值,并且与另一个表中的另一列(外键)具有“一对多”关系。但实际上在这个外键中存储的不是单个整数值,而是数字值用分号分隔的字符串。这种技术称为“多值字段”。事实上,这是没有关联表的“多对多”关系。

非常简化的方案:

Persons
-------------
id - Integer
name - String
vacancy_id - Integer (multi-value, Foreign key of Vacancies.id)

Vacancies
-------------
id - Integer
vacancy_name - String

我尝试使用 declarative_base 父类将类映射到表。但是在没有关联表的情况下找不到如何声明“多对多”关系。现在我有这样的代码。

Base = declarative_base()


class Vacancy(Base):
    __tablename__ = 'Vacancies'
    id = sa.Column(sa.Integer, name='id', primary_key=True, autoincrement=True)
    vacancy_name = sa.Column(sa.String(255), name='vacancy_name')


class Person(Base):
    __tablename__ = 'Persons'
    id = sa.Column(sa.Integer, name='id', primary_key=True, autoincrement=True)
    name = sa.Column(sa.String(255), name='name')
    vacancy_id = sa.Column(sa.Integer, ForeignKey(Vacancy.id), name='vacancy_id')
    vacancies = relationship(Vacancy)

在请求人期间,我有奇怪的行为:

  • 如果未指定 vacancy_id,我将 Person.vacancies 设为 None。
  • 如果 vacancy_id 指定为单个值(即“1”),则在 Person.vacancies 我得到 Vacancy 类的单个对象。
  • 如果 vacancy_id 指定为多个值(即“1;2;3”),在 Person.vacancies 我也得到无。

当然,我可以请求原始 Person.vacancy_id,用分号分隔,然后请求获取带有 ID 列表的空缺。

但我想知道——SqlAlchemy 是否可以处理“多值字段”?处理此类文件的最佳方式是什么?

更新 目前我做了以下解决方法来自动解析多值列。这应该添加到 Persons 类:

@orm.reconstructor
def load_on_init(self):
    if self.vacancy_id:
        ids = self.vacancy_id.split(';')
        self.vacancies = [x for x in Vacancy.query.filter(Vacancy.id.in_(ids)).all()]
    else:
        self.vacancies = []

空缺类应具有以下属性:

query = DBSession.query_property()

最后,我们必须为课堂使用准备会话:

engine = create_engine(CONNECTION_URI)
DBSession = scoped_session(sessionmaker(bind=engine))
Base = declarative_base()
4

1 回答 1

2

Access ODBC 对多值查找字段的支持非常有限。这些字段实际上是使用隐藏的关联表(名称类似f_1BC9E55B5578456EB5ACABC99BB2FF0B_vacancies)实现的,但这些表无法从 SQL 语句中访问:

SELECT * from f_1BC9E55B5578456EB5ACABC99BB2FF0B_vacancies

导致错误

Microsoft Access 数据库引擎找不到输入表或查询“”。确保它存在并且其名称拼写正确。

正如您所发现的,Access ODBC 将读取多个条目的键值并将它们显示为一个分号分隔的列表,我们可以解析,但我们无法更新这些值

UPDATE Persons SET vacancies = '1;2' WHERE id = 1

失败了

UPDATE 或 DELETE 查询不能包含多值字段。(-3209)

所以,TL;DR,如果您只需要从数据库中读取,那么您的解决方法可能就足够了,但是如果您需要修改这些多值字段,那么 Access ODBC 将无法为您完成工作。

于 2021-01-16T00:00:14.893 回答