PostgreSQL удаляет строку, если выполнено условие, иначе обновите какое-либо значение - PullRequest
1 голос
/ 24 мая 2019

Я пытаюсь удалить строку на основе простого условия, если условия выполняются, удалите строку, либо обновите строку. Обычно я помечаю свои данные is_deleted, поэтому выполните удаление, если is_deleted равно true, если нет, установите значение is_deleted в true.

Сейчас я делаю простой запрос, проверим is_deleted по запрашиваемым данным и сделаем что-нибудь на его основе.

Очень простой псевдокод, написанный на clojure ($ n - просто заполнитель для позиционных аргументов):

(defn find-by-username 
  [db username]
  "SELECT * FROM users WHERE username = $1") ;; to illustrate the query

(defn delete-by-username-impl
  [db username]
  "DELETE FROM users WHERE username = $1")

(defn set-is-deleted
  [db username]
  "UPDATE users SET is_deleted = true WHERE username = $1")

(defn delete-by-username 
  [db username]
  (let [user (find-by-username db username)]
    (if (:is-deleted user)
      (delete-by-username-impl db username)
      (set-is-deleted db username))))

Мне нужно только один раз попасть в БД.

Ответы [ 3 ]

1 голос
/ 25 мая 2019

Что вы имеете в виду, когда попали в базу данных только один раз?Запуск одного запроса?Затем вы можете объединить все запросы в один:

IF (SELECT is_deleted FROM users WHERE username = $1") THEN
  DELETE FROM users WHERE username = $1
ELSE
  UPDATE users SET is_deleted = true WHERE username = $1
END IF;

Если вы имеете в виду выполнение всех запросов вместе или ни одного из них в изолированном контексте (чтобы другие клиенты не могли изменить состояние, например флаг is_deleted, показапросы выполняются), вы можете заключить отдельные запросы в транзакцию, используя транзакцию базы данных :

Транзакции базы данных доступны, чтобы гарантировать, что несколько операций выполняются атомарно (т. е. всеили нет).Макрос clojure.java.jdbc / with-db -action создает соединение с поддержкой транзакций из спецификации базы данных.Используйте соединение с поддержкой транзакций на время транзакции:

(jdbc/with-db-transaction [trans-conn db-spec]
  (jdbc/insert! trans-conn :fruit {:name "Fig" :cost 12})
  (jdbc/insert! trans-conn :fruit {:name "Date" :cost 14}))
;; -> ({:grade nil, :unit nil, :cost 14, :appearance nil, :name "Date"})
0 голосов
/ 24 мая 2019

Есть два очевидных варианта

A.Вызовите функцию, чтобы сделать удаление для вас.Это может:

  1. заблокировать строку (SELECT ... FOR UPDATE)
  2. прочитать текущую настройку флага
  3. удалить строку, если установлен флаг
  4. установите флаг, если он не

B.Напишите триггер «BEFORE DELETE ».

Это может проверить состояние флага и, если он не установлен, установить его вместо удаления (вернуть NULL).Если флаг уже установлен, пусть операция удаления продолжится.

Триггеры иногда могут быть немного «волшебными» для моих вкусов.Если вы не знаете, что они там, это может сбить с толку.Однако в этом случае я думаю, что триггер, вероятно, является хорошим выбором.

0 голосов
/ 24 мая 2019

См. «Объединение действий с Quals» в https://wiki.postgresql.org/wiki/MergeTestExamples

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...