Автоматически обновлять значение при вставке / удалении другого - PullRequest
0 голосов
/ 17 октября 2019

У нас есть таблица, подобная приведенной ниже:

=# CREATE TABLE items (item_id INT NOT NULL, revision VARCHAR(2) NOT NULL, is_newest_rev BOOLEAN NOT NULL, UNIQUE (item_id,revision));

...

=# SELECT * FROM items;
 item_id | revision | is_newest_rev
---------+----------+---------------
     250 |       1A | f
     250 |       1B | t
     199 |       1F | t
      40 |       1A | f     <-note this, false
      40 |       1B | f     <-note this, false
      40 |       1C | t     <-note this, true

Таблица выше действительна.

Недопустима следующая таблица:

=# SELECT * FROM items;
 item_id | revision | is_newest_rev
---------+----------+---------------
     250 |       1A | f
     250 |       1B | t
     199 |       1F | t
      40 |       1A | f     <-note this, false
      40 |       1B | f     <-note this, false
      40 |       1C | t     <-note this, true
      40 |       1D | t     <-ERROR! 40 | 1C is already marked as true!

таблица также недействительна:

=# SELECT * FROM items;
 item_id | revision | is_newest_rev
---------+----------+---------------
     250 |       1A | f
     250 |       1B | t
     199 |       1F | t
      40 |       1A | f
      40 |       1B | f
      40 |       1C | f <-ERROR! 40 has no true values!

Мне нужно создать триггер (я думаю, что это так), чтобы автоматически изменять единственное истинное значение в списке для этой ревизии и идентификатора элементав значение false, а затем добавьте новое значение, указанное в запросе на вставку.

Другими словами, мне нужно, чтобы оно совпадало со следующим:

  • Отклонить любые запросы вставки, пытающиесявставить f в столбец is_newest_rev (только принимать t вставить запросы)

  • Автоматически изменять единственный экземпляр t в таблице (для этого item_id и ревизии) до f перед добавлением нового значения

  • Удаление одной или нескольких строк t автоматически изменит другие значения is_newest_rev (для этого item_id и ревизии) на t

  • Всегда проверяйте наличие хотя бы одногоnstance t для этого item_id и ревизии (никогда 0, никогда 2, ровно 1)

Пример:

=# SELECT * FROM items;
 item_id | revision | is_newest_rev
---------+----------+---------------
     250 |       1A | f
     250 |       1B | t
     199 |       1F | t
      40 |       1A | f
      40 |       1B | f
      40 |       1C | t

=# INSERT INTO items VALUES (40, '1D', 't');
INSERT 0 1

=# SELECT * FROM items;
 item_id | revision | is_newest_rev
---------+----------+---------------
     250 |       1A | f
     250 |       1B | t
     199 |       1F | t
      40 |       1A | f
      40 |       1B | f
      40 |       1C | f     <-
      40 |       1D | t     <- notice how 1C is now false and 1D is now true

=# DELETE FROM items WHERE item_id = '40' AND revision = '1A';
DELETE 1

=# SELECT * FROM items;
 item_id | revision | is_newest_rev
---------+----------+---------------
     250 |       1A | f
     250 |       1B | t
     199 |       1F | t
      40 |       1B | f
      40 |       1C | f
      40 |       1D | t      <- note all other values stayed the same

=# DELETE FROM items WHERE item_id = '40' AND is_newest_rev = 't';
DELETE 1

=# SELECT * FROM items;
 item_id | revision | is_newest_rev
---------+----------+---------------
     250 |       1A | f
     250 |       1B | t
     199 |       1F | t
      40 |       1B | f
      40 |       1C | t     <- note how 1D was removed and 1C was marked as true

=# DELETE FROM items WHERE is_newest_rev = 't';
DELETE 3

=# SELECT * FROM items;
 item_id | revision | is_newest_rev
---------+----------+---------------
     250 |       1A | t     <- 250, 1B is removed, 1A marked as true
      40 |       1B | t     <- 199, 1F completely removed, as no other 199s exist
                            <- 40, 1C is removed, 1B marked as true

Надеюсь, это достаточно объясняет то, что яищу. Если вам нужно, чтобы я объяснил больше, дайте мне знать

1 Ответ

1 голос
/ 17 октября 2019

Если revision всегда будет строкой из 2 символов, простой CTE может динамически сгенерировать для вас столбец is_latest_rev:

WITH latest_revs AS
  (SELECT DISTINCT(item_id) AS item_id,
              MAX(revision) as revision,
                       't' as is_newest_rev
   FROM items
   GROUP BY item_id)
SELECT i.item_id, i.revision, COALESCE(lr.newest_rev,'f')
FROM items i LEFT OUTER JOIN 
  latest_revs lr ON (i.item_id=lr.item_id AND i.revision=lr.revision)
ORDER BY item_id, revision;

Если вам просто нужен список последнихизменения, вы можете просто сделать:

SELECT DISTINCT(item_id), MAX(revision) FROM items GROUP BY item_id;

Раскрытие информации: я EnterpriseDB (EDB) сотрудник

...