Обновление и удаление вместе на PostgreSQL - PullRequest
4 голосов
/ 01 июля 2019

У меня проблема с моим запросом postgreSQL.Я должен сделать запрос с UPDATE до и DELETE после.Возвращаемое значение - количество ОБНОВЛЕНИЙ, но я хочу количество УДАЛЕНИЙ.Как я могу сделать?Большое спасибо.Я использую 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>

Ответы [ 2 ]

1 голос
/ 03 июля 2019

В этом конкретном случае вы можете делать то, что вы хотите. Из приведенных выше запросов я вижу, что:

  1. записи обновляются в первую очередь с одинаковыми значениями
  2. те же записи удаляются

Это имеет некоторые недостатки: 1. обновление каждой записи с помощью отдельного запроса вызывает ряд сетевых вызовов 2. предикаты в UPDATE и DELETE одинаковы, что затрудняет поддержание

Это можно решить так:

<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 выполняется только один сетевой вызов, и запрос возвращает количество удаленных записей.

0 голосов
/ 01 июля 2019

Вы можете выполнить несколько операторов 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>
...