我有一个遗留数据库,它是用自动递增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它应该使用“主机名”作为标识?如果是,怎么做?你知道吗
在这样的情况下,我发现最好对炼金术撒谎。告诉它自然键是主键。你知道吗
相关问题 更多 >
编程相关推荐