插入分区表时获取生成的键值

Posted

技术标签:

【中文标题】插入分区表时获取生成的键值【英文标题】:Get generated key value while inserting in partitioned table 【发布时间】:2013-04-02 06:32:28 【问题描述】:

您好,我在 Postgres 中有一个表格,比如 email_messages。它是分区的,因此无论我使用我的 java 应用程序执行的插入操作都不会影响主表,因为数据实际上是插入到子表中的。这是问题所在,我想获得一个自动生成的列值(比如 email_message_id 是大序列类型的)。 Postgres 将它作为 null 返回,因为没有在主表上进行插入。对于 oracle,我使用 GeneratedKeyHolder 来获取该值。但是我不能对 postgres 中的分区表做同样的事情。请帮帮我。

这是我们用于oracle的代码sn-p

public void createAndFetchPKImpl(final Entity pEntity,
  final String pStatementId, final String pPKColumnName) 


final SqlParameterSource parameterSource =
  new BeanPropertySqlParameterSource(pEntity);

  final String[] columnNames = new String[]"email_message_id";
  final KeyHolder keyHolder = new GeneratedKeyHolder();
  final int numberOfRowsEffected = mNamedParameterJdbcTemplate.update(
      getStatement(pStatementId), parameterSource, keyHolder, columnNames);
  pEntity.setId(ConversionUtil.getLongValue(keyHolder.getKey()));


【问题讨论】:

"GeneratedKeyHolder" 暗示您可能正在使用 Spring,但我们不必猜测。请详细说明。 JDBC 驱动程序版本,任何更高级别的抽象,如 JPA/Spring,您的映射代码等。 是的,我们使用的是 spring-jdbc 版本 3.1.1 。 Postgres 版本为 8.1 我得到 numberOfRowsEffected 为零和 keyHolder.getKey() 为空,即使插入正在表中发生。 好的,第一件事:您需要升级 PostgreSQL 昨天,8.1 不支持且已过时。它可能不会针对将于 4 月 4 日修复的重大安全问题进行修补:blog.hagander.net/archives/… 【参考方案1】:

当您在 PostgreSQL 中使用基于触发器的分区时,JDBC 驱动程序报告零行受到影响/插入是正常。这是因为原来的SQLUPDATEINSERTDELETE实际上并没有生效,主表上没有任何行发生变化。而是对一个或多个子表执行操作。

基本上,PostgreSQL 中的分区有点像 hack,这是它更明显的限制之一。

解决方法是:

INSERT/UPDATE/DELETE直接针对子表,而不是***表; 忽略结果行数;或 改用RULEs 和INSERT ... RETURNING(但它们有自己的问题)(不适用于分区)

【讨论】:

我尝试使用“RETURNING currval('email_messages_email_message_id_seq')”插入,但我仍然无法获得该值。但是,我可以通过使用存储过程进行插入来实现它。你能具体说明我如何使用返回子句获取值 @user1495565 您使用的是基于规则还是基于触发器的分区? 如果我使用规则而不是触发器(当前代码)更改我的分区,根据 postgres 当前的实现,它只允许无条件的 INSTEAD 规则包含 RETURNING;此外,同一事件的所有规则中最多可以有一个 RETURNING 子句。所以我不能从所有规则中返回值,因为我有同一个表的多个分区。 @mohansammeta 啊,好点,我忘了。所以你基本上必须根据第一两点在应用层解决它。 触发器有什么作用?如果它将相同的记录插入到主表中,它可以检索其主 ID,然后可以通过 Java 方法调用传递。

以上是关于插入分区表时获取生成的键值的主要内容,如果未能解决你的问题,请参考以下文章

全局索引和本地索引的区别

将数据插入 Hive 分区表时出错

Oracle间隔(interval)分区

MySQL分区表使用方法

如何获取自动生成的(主)键值?

js 对象按照键值(不分区大小写)排序,生成签名方法