import sqlalchemy as sa
from sqlalchemy.dialects.postgresql import insert as pg_insert
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
engine = sa.create_engine('postgresql+psycopg2://user:pass@hostname:port/db')
class Person(Base):
__tablename__ = 'people'
__table_args__ = {'postgresql_with_oids': True}
email = sa.Column(sa.Text, primary_key=True)
name = sa.Column(sa.Text, nullable=False)
Base.metadata.create_all(engine)
2条答案
按热度按时间uhry853o1#
只需添加最后一个
RETURNING
子句:字符串
对于插入的行返回
true
,对于更新的行返回false
。但是,这依赖于未记录的实现细节。有关详细说明,请参阅:添加OID(就像另一个答案中建议的那样)会增加成本,膨胀表并烧毁OID(如果你的表不是很小的话)。这就是为什么
default_with_oids
的一般设置很久以前就被更改为off
(Postgres 8.1)。Postgres 11的手册:在用户表中使用OID被认为是不推荐的,因此大多数安装应该禁用此变量。需要特定表的OID的应用程序应该在创建表时指定
WITH OIDS
。后来的版本甚至完全删除了设置
default_with_oids
。af7jpaap2#
从插入的postgresql文档:
在成功完成时,一个命令行命令返回一个命令标记,格式如下:
字符串
count是插入或更新的行数。如果count正好为1,并且目标表具有OID,则oid是分配给插入行的序号。单行必须是插入的而不是更新的。否则oid为零。
因此,可以通过检查查询消息来检查更新与插入
可以使用语法使用
OIDs
创建表型
,或者
OIDs
可以在现有表上启用,型
使用sqlalchemy,可以使用
OIDs
创建一个表,如下所示:型
冲突时插入语句可以这样构造:
型
最后,一旦执行了该语句,就会返回一个结果代理,它的属性
lastrowid
对应于查询消息INSERT oid count
中的oid
。因此,如果第一次执行
stmt
,型
由于创建了新行,
r.lastrowid
将输出an integer > 0
每隔一次,
r.lastrowid
将输出0
。如果你需要一次跟踪多行的upsert,你可以设置额外的列作为标志,这些标志是从insert语句的on conflict do update部分更新的。
有很多方法可以做到这一点,这取决于具体的要求。这里是一个替代方案。
添加额外列
conflict_updated_at = sa.Column(sa.Datetime(True))
将upsert定义更改为
型