【问题标题】:update tables with computed columns in sqlalchemy用 sqlalchemy 中的计算列更新表
【发布时间】:2013-04-30 04:35:03
【问题描述】:

我正在使用 SQLalchemy 在旧版 MSSQL 数据库中工作,为此我有一个声明性映射。
该数据库有几个具有计算列的表。我可以很好地阅读它们,但是(当然)写入计算列不起作用。但是,当我创建并尝试保存 ORM 对象时,SQLAlchemy 仍然尝试在这些列中保存“无”值,从而导致错误。

我在网上找到了一些示例,这些示例应该使用 SQLAlchemy 的 hybrid_property 装饰器将特定列设置为“只读”,但即使在实施之后,仍然会出现相同的错误 (The column "tlog_real_timehh" cannot be modified because it is either a computed column or is the result of a UNION operator.)。

代码如下——映射:

class transactionlog(Base):
    __tablename__ = 'transactionlog'
    tlog_id = Column(VARCHAR(length=36), primary_key=True, nullable=False)
    tlog_ppl_id = Column(VARCHAR(length=36), ForeignKey('people.ppl_id'))
    tlog_evtt_id = Column(VARCHAR(length=5))
    tlog_testrun = Column(BIT())
    tlog_Data = Column(NVARCHAR(length=300))
    tlog_price = Column(DECIMAL(precision=18, scale=2))
    tlog_comment = Column(NVARCHAR(length=1000))
    _tlog_real_timehh = Column('tlog_real_timehh', INTEGER())
    _tlog_real_timemm = Column('tlog_real_timemm', INTEGER())
    _tlog_real_timess = Column('tlog_real_timess', INTEGER())
    _tlog_fin_booking = Column('tlog_fin_booking', BIT())

    @hybrid_property
    def tlog_real_timehh(self):
        return self._tlog_real_timehh

    @tlog_real_timehh.setter
    def tlog_real_timehh(self, tlog_real_timehh):
        self._tlog_real_timehh = tlog_real_timehh

    @hybrid_property
    def tlog_real_timemm(self):
        return self._tlog_real_timemm

    @tlog_real_timemm.setter
    def tlog_real_timemm(self, tlog_real_timemm):
        self._tlog_real_timemm = tlog_real_timemm

    @hybrid_property
    def tlog_real_timess(self):
        return self._tlog_real_timess

    @tlog_real_timess.setter
    def tlog_real_timess(self, tlog_real_timess):
        self._tlog_real_timess = tlog_real_timess

    @hybrid_property
    def tlog_fin_booking(self):
        return self._tlog_fin_booking

    @tlog_fin_booking.setter
    def tlog_fin_booking(self, tlog_fin_booking):
        self._tlog_fin_booking = tlog_fin_booking

以及应该添加新记录的代码:

    rem = Transactionlog()
    rem.tlog_testrun = 0
    rem.tlog_evtt_id = 'rem'
    rem.tlog_Data = None
    rem.tlog_comment = 'reminder'
    rem.tlog_price = 0
    db.session.add(rem)
    db.session.flush()

我希望 hybrid_property 代码将计算字段设置为只读,但似乎 SQLAlchemy 仍然尝试根据映射代码将它们填充到 INSERT 语句中。 (当我查看 SQL 语句时,我可以看到这一点。我无法发布 SQL 语句,因为我对对象进行了一些缩写,以便在 StackOverflow 上没有任何敏感数据)。

问题是,为什么 SQLAlchemy 仍然尝试插入 tlog_real_timehh、tlog_real_timemm、tlog_real_timess 和 tlog_fin_booking 的值,我该如何防止这种情况发生?

感谢您给我的任何指点。
埃里克

【问题讨论】:

    标签: python orm sqlalchemy


    【解决方案1】:

    使用FetchedValue 标记server-generated columns

    from sqlalchemy import *
    from sqlalchemy.orm import *
    from sqlalchemy.ext.declarative import declarative_base
    
    Base = declarative_base()
    
    class A(Base):
        __tablename__ = 'a'
    
        id = Column(Integer, autoincrement=False, primary_key=True)
        firstname = Column(String(50))
        lastname = Column(String(50))
        fullname = Column(String(100), FetchedValue())
    
    e = create_engine("mssql+pyodbc://scott:tiger@ms_2005", echo=True)
    Base.metadata.drop_all(e)
    
    e.execute("""
        CREATE TABLE a (
                id INTEGER PRIMARY KEY,
                firstname VARCHAR(50),
                lastname VARCHAR(50)
            )
    """)
    e.execute("ALTER TABLE a ADD fullname AS firstname + ' ' + lastname")
    
    sess = Session(e)
    
    sess.add_all([
        A(id=1, firstname='ed', lastname='jones'),
        A(id=2, firstname='wendy', lastname='smith'),
        A(id=3, firstname='jack', lastname='bean')
    ])
    sess.commit()
    
    assert [
        fname for fname, in
        sess.query(A.fullname).order_by(A.id)
    ] == ['ed jones', 'wendy smith', 'jack bean']
    
    
    e.execute("DROP TABLE a")
    

    【讨论】:

    • 已实现,经过测试,基本可行!,谢谢 zzzeek!
    猜你喜欢
    • 2013-06-23
    • 2019-07-02
    • 2019-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多