PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Làm cách nào để lấy một cột có các số liên tiếp, tăng dần mà không bị thiếu số nào?

Điều chỉnh điều này từ một câu trả lời trước đó. Loại nội dung này thường xảy ra khi các ứng dụng muốn có thứ tự tab cho các biến (đọc:bản ghi trong mô hình EAV), cũng có thể là (một phần của) khóa thay thế.

  • priority trường cần được giữ liên tiếp. [đây là thứ tự tab ]
  • trên CHÈN:tất cả các bản ghi có mức độ ưu tiên> =bản ghi mới sẽ được tăng mức độ ưu tiên của chúng
  • tương tự:trên DELETE -> giảm dần
  • nếu mức độ ưu tiên của bản ghi bị thay đổi bởi CẬP NHẬT, các bản ghi giữa giá trị ưu tiên cũ và mới sẽ có mức độ ưu tiên của chúng được chuyển lên hoặc xuống.
  • để tránh lệnh gọi kích hoạt đệ quy:
    • các bản cập nhật dựa trên trình kích hoạt lật flipflag của bất kỳ bản ghi nào họ chạm vào.
    • Và họ kiểm tra old.flipflag=new.flipflag để phát hiện thực các bản cập nhật. (những thứ không phải do kích hoạt)
        -- Make some data
DROP SCHEMA tmp CASCADE;
CREATE SCHEMA tmp ;
SET search_path=tmp;

CREATE TABLE fruits
        ( id INTEGER NOT NULL PRIMARY KEY
        , priority INTEGER NOT NULL
        , flipflag boolean NOT NULL default false
        , zname varchar NOT NULL
        , CONSTRAINT unique_priority UNIQUE (priority) DEFERRABLE INITIALLY DEFERRED
        );
INSERT INTO fruits(id,zname,priority) VALUES
 (1  , 'Pear' ,4)
,(2  , 'Apple' ,2)
,(3  , 'Orange' ,1)
,(4  , 'Banana' ,3)
,(5  , 'Peach' ,5)
        ;

        -- Trigger functions for Insert/update/delete
CREATE function shift_priority()
RETURNS TRIGGER AS $body$

BEGIN
        UPDATE fruits fr
        SET priority = priority +1
        , flipflag = NOT flipflag       -- alternating bit protocol ;-)
        WHERE NEW.priority < OLD.priority
        AND OLD.flipflag = NEW.flipflag -- redundant condition
        AND fr.priority >= NEW.priority
        AND fr.priority < OLD.priority
        AND fr.id <> NEW.id             -- exlude the initiating row
                ;
        UPDATE fruits fr
        SET priority = priority -1
        , flipflag = NOT flipflag
        WHERE NEW.priority > OLD.priority
        AND OLD.flipflag = NEW.flipflag
        AND fr.priority <= NEW.priority
        AND fr.priority > OLD.priority
        AND fr.id <> NEW.id
        ;
        RETURN NEW;
END;

$body$
language plpgsql;

CREATE function shift_down_priority()
RETURNS TRIGGER AS $body$

BEGIN

        UPDATE fruits fr
        SET priority = priority -1
        , flipflag = NOT flipflag       -- alternating bit protocol ;-)
        WHERE fr.priority > OLD.priority
                ;
        RETURN NEW;
END;

$body$
language plpgsql;

CREATE function shift_up_priority()
RETURNS TRIGGER AS $body$

BEGIN
        UPDATE fruits fr
        SET priority = priority +1
        , flipflag = NOT flipflag       -- alternating bit protocol ;-)
        WHERE fr.priority >= NEW.priority
                ;
        RETURN NEW;
END;

$body$
language plpgsql;

        -- Triggers for Insert/Update/Delete
CREATE TRIGGER shift_priority_u
        AFTER UPDATE OF priority ON fruits
        FOR EACH ROW
        WHEN (OLD.flipflag = NEW.flipflag AND OLD.priority <> NEW.priority)
        EXECUTE PROCEDURE shift_priority()
        ;
CREATE TRIGGER shift_priority_d
        AFTER DELETE ON fruits
        FOR EACH ROW
        EXECUTE PROCEDURE shift_down_priority()
        ;
CREATE TRIGGER shift_priority_i
        BEFORE INSERT ON fruits
        FOR EACH ROW
        EXECUTE PROCEDURE shift_up_priority()
        ;

        -- Do some I/U/D operations
\echo Pears are Okay
UPDATE fruits
SET priority = 1
WHERE id=1; -- 1,4

SELECT * FROM fruits ORDER BY priority;

\echo dont want bananas
DELETE FROM fruits WHERE id = 4;
SELECT * FROM fruits ORDER BY priority;

\echo  We want Kiwis
INSERT INTO fruits(id,zname,priority) VALUES (4  , 'Kiwi' ,3) ;
SELECT * FROM fruits ORDER BY priority;

Kết quả:

Pears are Okay
UPDATE 1
 id | priority | flipflag | zname  
----+----------+----------+--------
  1 |        1 | f        | Pear
  3 |        2 | t        | Orange
  2 |        3 | t        | Apple
  4 |        4 | t        | Banana
  5 |        5 | f        | Peach
(5 rows)

dont want bananas
DELETE 1
 id | priority | flipflag | zname  
----+----------+----------+--------
  1 |        1 | f        | Pear
  3 |        2 | t        | Orange
  2 |        3 | t        | Apple
  5 |        4 | t        | Peach
(4 rows)

We want Kiwis
INSERT 0 1
 id | priority | flipflag | zname  
----+----------+----------+--------
  1 |        1 | f        | Pear
  3 |        2 | t        | Orange
  4 |        3 | f        | Kiwi
  2 |        4 | f        | Apple
  5 |        5 | f        | Peach
(5 rows)



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Các cải tiến về báo cáo tiến độ trong PostgreSQL 12

  2. Cách triển khai PostgreSQL khả dụng cao với Điểm cuối duy nhất cho WordPress

  3. pg gem '0.14.0' trên Mountain Lion không thành công

  4. Làm thế nào để giữ cho dữ liệu không sắp xếp?

  5. Hàm MAX () trong PostgreSQL