Alireza Asked: 2014-02-09 03:36:11 +0800 CST2014-02-09 03:36:11 +0800 CST 2014-02-09 03:36:11 +0800 CST 从postgres中的分区表返回ID? 772 当我插入一条记录时,我需要返回插入的 id RETURNING。问题是表是分区的,在分区表中我不能使用RETURNING。我一次运行多个查询,所以我急需RETURNING. 有没有办法做到这一点? postgresql partitioning 2 个回答 Voted Best Answer Daniel Vérité 2014-02-09T08:08:16+08:002014-02-09T08:08:16+08:00 假设父母的表格是这样的: CREATE TABLE parent AS ( id not null default nextval('parent_id_seq'::regclass) ... other columns ... ); 无论您是使用规则还是触发器将 INSERT 转移到子表中,在 INSERT 之后您可以立即使用: SELECT currval('parent_id_seq'::regclass); 获取id会话的最后一个插入,独立于并发 INSERT,每个会话都有它自己获得的最后一个序列值的副本。 Avarkx 2014-02-09T11:40:18+08:002014-02-09T11:40:18+08:00 如果不了解您当前如何管理分区表,则相对难以评估您可以采取哪些措施来规避此限制。假设您使用的是触发器范例,为了RETURNING按预期工作,您必须将函数中的子句从RETURNto更改为,因为子句永远不会从前一种情况接收插入的值(因为它们实际上从未插入到主表)。进行此更改也会将插入的行传递到主表,从而允许子句接收结果。 BEFORE INSERTNULLNEWRETURNINGRETURNING 但是,这意味着会发生双重写入,因此需要AFTER INSERT触发函数来删除重复的元素。虽然这显然会产生额外的开销并有效地减半效率,但它的影响仍然小于RULE范式(无论如何可能需要同样多的工作),当然在批量插入场景中除外。这是一致性和可维护性的性能权衡,但只要理解这一点并且首先使用分区表的好处是保持 SLA 的满足,我认为这是一个可以接受的让步。 这是完整的SQL Fiddle以显示我在操作中所描述的内容。请注意,NewID()顶部的函数只是为了说明在没有可用序列的情况下它是如何工作的,并且绝不暗示该函数本身在任何方面都是一个好主意(如果您愿意,可以使用适当的全局 UID 插件走那条路)。
假设父母的表格是这样的:
无论您是使用规则还是触发器将 INSERT 转移到子表中,在 INSERT 之后您可以立即使用:
SELECT currval('parent_id_seq'::regclass);
获取
id
会话的最后一个插入,独立于并发 INSERT,每个会话都有它自己获得的最后一个序列值的副本。如果不了解您当前如何管理分区表,则相对难以评估您可以采取哪些措施来规避此限制。假设您使用的是触发器范例,为了
RETURNING
按预期工作,您必须将函数中的子句从RETURN
to更改为,因为子句永远不会从前一种情况接收插入的值(因为它们实际上从未插入到主表)。进行此更改也会将插入的行传递到主表,从而允许子句接收结果。BEFORE INSERT
NULL
NEW
RETURNING
RETURNING
但是,这意味着会发生双重写入,因此需要
AFTER INSERT
触发函数来删除重复的元素。虽然这显然会产生额外的开销并有效地减半效率,但它的影响仍然小于RULE
范式(无论如何可能需要同样多的工作),当然在批量插入场景中除外。这是一致性和可维护性的性能权衡,但只要理解这一点并且首先使用分区表的好处是保持 SLA 的满足,我认为这是一个可以接受的让步。这是完整的SQL Fiddle以显示我在操作中所描述的内容。请注意,
NewID()
顶部的函数只是为了说明在没有可用序列的情况下它是如何工作的,并且绝不暗示该函数本身在任何方面都是一个好主意(如果您愿意,可以使用适当的全局 UID 插件走那条路)。