如何告诉SQLAlchemy使用不同的身份规则会话.合并(而不是PK)?

2024-04-24 07:26:44 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个遗留数据库,它是用自动递增ID盲目创建的,尽管表中有一个完全有效的自然键。你知道吗

这最终导致代码乱七八糟:

Fetch row with natural key 'x'
if exists:
    update row with NK 'x'
else:
    insert row with NK 'x'

基本上是一个叛逆者。你知道吗

SQLAlchemy的Session.merge()涵盖了这个用例(upsert)。但是SA只会查看表的主键来协调它是否必须执行插入或更新。然而,在现有的数据库中,PK并不代表行的真正身份,这与它应该做的相反。因此,相同的标识可以出现在多个自动增量标识中。还有其他一些业务规则可以确保唯一性。但是今天的ID1可以是明天的ID3246!你知道吗

由于太多的遗留应用程序依赖于现有的结构,因此目前没有好的方法以合理的方式修改DB。你知道吗

为了一个具体的例子,假设表中有网络设备,并将它们的主机名作为自然密钥。电流分贝如下所示:

CREATE TABLE device (
    id SERIAL PRIMARY KEY,
    hostname TEXT UNIQUE,
    some_other_column TEXT
)

相应的SA模型:

class Device(Base):
    id = Column(Integer, primary_key=True)
    hostname = Column(String(256))
    some_other_column = Column(String(20))

我希望能够做到以下几点:

mydevice = Device(hostname='hello-world', some_other_column='foo')
merged_device = session.merge(mydevice)
session.commit()

在本例中,我希望SA执行“insert or update”。但在当前模型中,这实际上会导致错误(由于唯一主机名约束)。你知道吗

I可以指定hostname列作为SA模型中的主键(并保持DB中的PK不变)。但这看起来有点老套。有没有更明确、更容易理解的方法告诉SQLAlchemy它应该使用“主机名”作为标识?如果是,怎么做?你知道吗


Tags: key模型数据库withsaupdatecolumnsome
1条回答
网友
1楼 · 发布于 2024-04-24 07:26:44

在这样的情况下,我发现最好对炼金术撒谎。告诉它自然键是主键。你知道吗

class Device(Base):
    hostname = Column(String(256), primary_key=True)
    some_other_column = Column(String(20))

相关问题 更多 >