【问题标题】:Postgresql batch INSERT/UPDATE with externally provided IDsPostgresql 使用外部提供的 ID 批量插入/更新
【发布时间】:2015-06-12 16:52:53
【问题描述】:

我有一张表,里面有我需要在 cron 上合并更新的实体(人员、公司等)。批量这样做很重要,因为两个数据集都是任意大的(我发现一次一个需要数年时间)。两端都带有我需要检查的 ExternalIdentifer (EXID)。一直以来,任何 INSERT 都需要包含我的框架服务器提供的内部 ID(整数)。如有必要,我可以保证这些 ID 是连续的整数。

逻辑如下:

  • 如果 EXID 存在,则直接对其执行 UPDATE。
  • 否则,
    • 如果 EntityName 存在,则执行 UPDATE 否则,使用 ID 执行 INSERT 由框架服务器提供

简化的表格列(请原谅我缺乏格式知识)

列名 |数据类型

  1. “实体名称”| “性格不同”
  2. “外部标识符”| “性格不同”

被更新的表也有框架提供的内部ID:

  1. “实体标识”| “整数”

所以问题归结为,有没有一种快速的方法可以使用框架提供的 ID 批量执行此操作?

编辑:这是通过从 Java 执行的 SQL 完成的。我更喜欢主要在 SQL 中执行此操作,但部分可以在 Java 中完成。

【问题讨论】:

    标签: sql postgresql


    【解决方案1】:

    我发现在许多语句中做到这一点并不难。如果临时表在您的控制之下并且不会在此事务期间被修改,则可以通过这种方式完成此解决方案。

    简短回答: 本质上,更新是使用两个表的交集完成的。然后在继续之前将它们移除。之后,一切都完成了,只剩下插入了。我们从框架中获取一些连续的 ID,从起始 ID 创建一个序列序列,并使用该序列为这些 ID 创建一个新的序列键列。

    -- Do this once to create sequence
    create sequence erm.temporary_new_id;
    

    SQL:

    -- Update any that have matching externalidentifier
    update erm.entity set 
    entityname = up.entityname
    
    from (select * from erm.temp_entity_import where externalidentifier in
    
    (select externalidentifier from erm.entity
    intersect
    select externalidentifier from erm.temp_entity_import)) as up
    
    where erm.entity.externalidentifier = up.externalidentifier;
    
    -- Now remove those from the temp table and return the # of affected rows
    with del as (delete from erm.temp_entity_import where externalidentifier in
    
    (select externalidentifier from erm.entity
    intersect
    select externalidentifier from erm.temp_entity_import) returning true)
    select count(*) as rowcount from del;
    
    -- Update any with matching entityname
    update erm.entity set 
    externalidentifier = up.externalidentifier
    
    from (select * from erm.temp_entity_import where entityname in
    
    (select entityname from erm.entity
    intersect
    select entityname from erm.temp_entity_import)) as up
    
    where erm.entity.entityname = up.entityname;
    
    -- Now remove those from the temp table and return the # of affected rows
    with del as (delete from erm.temp_entity_import where entityname in
    
    (select entityname from erm.entity
    intersect
    select entityname from erm.temp_entity_import) returning true)
    select count(*) as rowcount from del;
    
    -- Grab the number of rows left as the number to be inserted so we know how many IDs to claim
    select count(temp_entity_id) from erm.temp_entity_import;
    
    -- Set the serial keygen to start at the id chunk we allocated and add the row
    alter sequence erm.temporary_new_id restart with STARTING_ID_NUM;
    alter table erm.temp_entity_import add column entityid integer default  nextval('erm.temporary_new_id');
    
    -- Insert them all
    insert into erm.entity (entityid, entityname, externalidentifier)
    select t.entityid, t.entityname, t.externalidentifier
    from erm.temp_entity_import as t;
    
    -- Delete from temp table (we can just wipe it)
    delete from erm.temp_entity_import;
    
    -- Remove the id column for next time
    alter table erm.temp_entity_import drop column entityid;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-03-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-29
      • 2011-04-15
      相关资源
      最近更新 更多