Возвращать значения столбца до ОБНОВЛЕНИЯ, используя только SQL - Версия PostgreSQL

У меня есть связанный вопрос , но это другая часть МОИ головоломка.

Я хотел бы получить СТАРОЕ ЗНАЧЕНИЕ столбца из строки, которая была ОБНОВЛЕНА - БЕЗ использования триггеров (ни хранимых процедур, ни каких-либо других дополнительных сущностей, не относящихся к SQL / запросам).

У меня есть такой запрос:

   UPDATE my_table
      SET processing_by = our_id_info -- unique to this worker
    WHERE trans_nbr IN (
                        SELECT trans_nbr
                          FROM my_table
                         GROUP BY trans_nbr
                        HAVING COUNT(trans_nbr) > 1
                         LIMIT our_limit_to_have_single_process_grab
                       )
RETURNING row_id;

Если бы я мог выполнить «FOR UPDATE ON my_table» в конце подзапроса, это было бы идеальным (и исправило бы мой другой вопрос / проблему). Но это не сработает: не может быть этого И «GROUP BY» (что необходимо для определения COUNT из trans_nbr). Тогда я мог бы просто взять эти trans_nbr и сначала выполнить запрос, чтобы получить (скоро будут) прежние значения processing_by.

Я пробовал делать что-то вроде:

   UPDATE my_table
      SET processing_by = our_id_info -- unique to this worker
     FROM my_table old_my_table
     JOIN (
             SELECT trans_nbr
               FROM my_table
           GROUP BY trans_nbr
             HAVING COUNT(trans_nbr) > 1
              LIMIT our_limit_to_have_single_process_grab
          ) sub_my_table
       ON old_my_table.trans_nbr = sub_my_table.trans_nbr
    WHERE     my_table.trans_nbr = sub_my_table.trans_nbr
      AND my_table.processing_by = old_my_table.processing_by
RETURNING my_table.row_id, my_table.processing_by, old_my_table.processing_by

Но это не сработало; old_my_table не отображается вне соединения; предложение RETURNING не учитывает этого.

Я давно потерял счет всем своим попыткам; Я исследую это буквально часами.

Если бы я мог просто найти надежный способ заблокировать строки в моем подзапросе - и ТОЛЬКО эти строки, и КОГДА происходит подзапрос - все проблемы параллелизма, которых я пытаюсь избежать, исчезли бы ...


ОБНОВЛЕНИЕ: [ВЫТИРАЕТ ЯЙЦО С ЛИЦА] Хорошо, у меня была опечатка в неуниверсальном коде выше, который я написал «не работает»; да ... благодаря Эрвину Брандштеттеру , ниже, который заявил, что будет, я повторил это (после ночного сна, освеженных глаз и банана для завтрака). Поскольку мне потребовалось так много / сложно найти такое решение, возможно, мое затруднение того стоит? По крайней мере, это сейчас на ТАК для потомков ...:>

То, что у меня теперь (это работает), выглядит следующим образом:

   UPDATE my_table
      SET processing_by = our_id_info -- unique to this worker
     FROM my_table AS old_my_table
    WHERE trans_nbr IN (
                          SELECT trans_nbr
                            FROM my_table
                        GROUP BY trans_nbr
                          HAVING COUNT(*) > 1
                           LIMIT our_limit_to_have_single_process_grab
                       )
      AND my_table.row_id = old_my_table.row_id
RETURNING my_table.row_id, my_table.processing_by, old_my_table.processing_by AS old_processing_by

COUNT (*) соответствует предложению от Flimzy в комментарии к моему другому ( ссылка выше) вопрос. (Я был более конкретен, чем необходимо. [В данном случае.])

Пожалуйста, посмотрите мой другой вопрос для правильной реализации параллелизма и даже неблокирующей версии; ЭТОТ запрос просто показывает, как получить старые и новые значения из обновления, игнорируя плохие / неправильные биты параллелизма.

42
задан Community 23 May 2017 в 12:25
поделиться