是否可以将 session.insert 用于 SQLAlchemy 中的一对一关系?

Posted

技术标签:

【中文标题】是否可以将 session.insert 用于 SQLAlchemy 中的一对一关系?【英文标题】:Is it possible to use session.insert for one to main relationships in SQLAlchemy? 【发布时间】:2019-08-01 11:02:11 【问题描述】:

我已阅读以下链接: Sqlalchemy adding multiple records and potential constraint violation

使用 SQLAlchemy 核心库执行插入是更快的选择,而不是 ORM 的 session.add() 方法:

即:

session.add()

应替换为:

session.execute(Entry.__table__.insert(), params=inserts)

在以下代码中,我尝试将 .add 替换为 .insert

from sqlalchemy import Column, DateTime, String, Integer, ForeignKey, func
from sqlalchemy.orm import relationship, backref
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()


class Department(Base):
    __tablename__ = 'department'
    id = Column(Integer, primary_key=True)
    name = Column(String)


class Employee(Base):
    __tablename__ = 'employee'
    id = Column(Integer, primary_key=True)
    name = Column(String)
    # Use default=func.now() to set the default hiring time
    # of an Employee to be the current time when an
    # Employee record was created
    hired_on = Column(DateTime, default=func.now())
    department_id = Column(Integer, ForeignKey('department.id'))
    # Use cascade='delete,all' to propagate the deletion of a Department onto its Employees
    department = relationship(
        Department,
        backref=backref('employees',
                        uselist=True,
                        cascade='delete,all'))


from sqlalchemy import create_engine

engine = create_engine('postgres://blah:blah@blah:blah/blah')

from sqlalchemy.orm import sessionmaker

session = sessionmaker()
session.configure(bind=engine)
Base.metadata.create_all(engine)

d = Department(name="IT")
emp1 = Employee(name="John", department=d)
s = session()
s.add(d)
s.add(emp1)
s.commit() 


s.delete(d)  # Deleting the department also deletes all of its employees.
s.commit()
s.query(Employee).all()

#插入选项尝试

from sqlalchemy.dialects.postgresql import insert
d = insert(Department).values(name="IT")
d1 = d.on_conflict_do_nothing()
s.execute(d1)
emp1 = insert(Employee).values(name="John", department=d1)
emp1 = emp1.on_conflict_do_nothing()
s.execute(emp1)

我收到的错误:

sqlalchemy.exc.CompileError: Unconsumed column names: department

我不太了解语法以及如何以正确的方式进行操作,我是 SQLAlchemy 的新手。

看来我的问题类似于How to get primary key columns in pd.DataFrame.to_sql insertion method for PostgreSQL "upsert" ,因此有可能通过回答我们的任何一个问题,您可以同时帮助两个人;-)

【问题讨论】:

【参考方案1】:

我也是 SQLAlchemy 的新手,但这是我发现的:

使用您的确切代码,仅使用“s.execute(d1)”添加部门不起作用,所以我将其更改为以下,它确实有效:

with engine.connect() as conn:
        d = insert(Department).values(name="IT")
        d1 = d.on_conflict_do_nothing()
        conn.execute(d1)

我在 SQLAlchemy 文档中发现,在过去,当您尝试使用实际上并不存在的虚拟列时,这只是一个警告。但从 0.8 版本开始,它已被更改为异常。

因此,我不确定您是否可以使用插入来做到这一点。我认为 SQLAlchemy 在使用 session.add() 时会以其他方式在幕后进行。也许一些专家可以在这里详细说明。

我希望这会有所帮助。

【讨论】:

以上是关于是否可以将 session.insert 用于 SQLAlchemy 中的一对一关系?的主要内容,如果未能解决你的问题,请参考以下文章

是否可以将查询参数传递给 Django % url % 模板标签?

是否可以在视图django中添加方法,用于在httpresponse中返回方法返回字符串的类视图中[关闭]

将 ARC 用于新项目是不是为时过早?

ISNUMERIC() 不适用于小数

是否可以将 s-s-rS 报告导出到 Excel,报告的图表作为 Excel 图表而不是图像?

带图表的历史表示