在 PostgreSQL 上一起更新和删除

Update and delete together on PostgreSQL

我的 postgreSQL 查询有问题。 我必须在之前使用 UPDATE 并在之后使用 DELETE 进行查询。 return 值是更新的数量,但我想要删除的数量。 我能怎么做?非常感谢你。 我用的是 myBatis.

<update id="updateSpotMetaDataTagIdsToDelete">
    <bind name="simulatedById" value="_parameter.spotUpdate.userOwner.getSimulatedById()" />

    <foreach item="id" collection="spotUpdate.spotMetaDataTagIdsToDelete" separator=";" >
        UPDATE spotsmetadatatags
        SET updatedate = now(),
        simulatedBy = #{simulatedById},
        fkuserowner = #{spotUpdate.userOwner.id},
        sessionId = #{spotUpdate.userOwner.sessionId}
        WHERE
        id = #{id}
        AND fkIdSpot = #{spotUpdate.fkIdSpot}
        AND (SELECT COUNT(*)
        FROM spots as s
        WHERE s.id = #{spotUpdate.fkIdSpot}
        AND s.fkIdOrganization = #{spotUpdate.userOwner.organization.id}) = 1
    </foreach>;

    DELETE FROM spotsmetadatatags
    WHERE fkIdSpot = #{spotUpdate.fkIdSpot}
    AND id IN (
    <foreach item="id" collection="spotUpdate.spotMetaDataTagIdsToDelete" separator="," >
        #{id}
    </foreach>
    )
    AND (SELECT COUNT(*)
    FROM spots as s
    WHERE s.id = #{spotUpdate.fkIdSpot}
    AND s.fkIdOrganization = #{spotUpdate.userOwner.organization.id}) = 1;
</update>

您可以一次执行多个 SQL 语句,但它应该属于同一个操作,如多个更新语句或多个删除语句。您不能在同一个映射器中混合更新和删除。

示例如果要删除多个 sql 语句。

<delete id="delete" parameterType="map">
    DELETE FROM table_a where X=${frommap};
    DELETE FROM table_b where X=${frommap};
    DELETE FROM table_c where X=${frommap}
</delete>

在这种特殊情况下,您可以随心所欲。从上面的查询中我可以看到:

  1. 具有相同值的记录先一条一条更新
  2. 相同的记录被删除

这有一些低效:

  1. 使用单独的查询更新每条记录会导致大量网络调用
  2. UPDATEDELETE 中的谓词相同,因此更难维护

可以这样解决:

<delete id="updateSpotMetaDataTagIdsToDelete">
    <bind name="simulatedById" value="_parameter.spotUpdate.userOwner.getSimulatedById()" />

    with updated as (
        UPDATE spotsmetadatatags
        SET updatedate = now(),
        simulatedBy = #{simulatedById},
        fkuserowner = #{spotUpdate.userOwner.id},
        sessionId = #{spotUpdate.userOwner.sessionId}
        WHERE
        id IN (
          <foreach item="id" collection="spotUpdate.spotMetaDataTagIdsToDelete" separator="," >
           #{id}
          </foreach>
        )
        AND fkIdSpot = #{spotUpdate.fkIdSpot}
        AND (SELECT COUNT(*)
        FROM spots as s
        WHERE s.id = #{spotUpdate.fkIdSpot}
        AND s.fkIdOrganization = #{spotUpdate.userOwner.organization.id}) = 1
        RETURNING id
    )   
    DELETE FROM spotsmetadatatags AS s
    USING updated AS u
    WHERE u.id = s.id
</delete>

通过这种方式您可以删除重复,只执行一个网络调用而不是 N 并且查询将 return 删除记录的数量。