sql >> データベース >  >> RDS >> PostgreSQL

SQLで優先順位を実装する方法(postgres)

    さて、これが優先順位をユニークで連続したものに保つための私の試みです。トリガー+関数によって実装されます。難しい部分は、トリガー内からの更新から生じる可能性のある無限の再帰を回避することです。これは、テーブル内に配置する必要がある汚れ/色のフラグによって解決されます。その値は重要ではありません。変更のみ。

    DROP SCHEMA tmp CASCADE;
    CREATE SCHEMA tmp ;
    SET search_path=tmp;
    
    CREATE TABLE fruits
            ( id INTEGER NOT NULL PRIMARY KEY
            , zname varchar NOT NULL
            , priority INTEGER NOT NULL
            , flipflag boolean NOT NULL default false
            , 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)
            ;
    
    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 TRIGGER shift_priority
            AFTER UPDATE OF priority ON fruits
            FOR EACH ROW
            WHEN (OLD.flipflag = NEW.flipflag AND OLD.priority <> NEW.priority)
            EXECUTE PROCEDURE shift_priority()
            ;
    
    UPDATE fruits
    SET priority = 1
    WHERE id=1;
    

    結果:

    SELECT * FROM fruits ORDER BY id;
    NOTICE:  drop cascades to 2 other objects
    DETAIL:  drop cascades to table tmp.fruits
    drop cascades to function tmp.shift_priority()
    DROP SCHEMA
    CREATE SCHEMA
    SET
    NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "fruits_pkey" for table "fruits"
    NOTICE:  CREATE TABLE / UNIQUE will create implicit index "unique_priority" for table "fruits"
    CREATE TABLE
    INSERT 0 4
    CREATE FUNCTION
    CREATE TRIGGER
    UPDATE 1
     id | zname  | priority | flipflag 
    ----+--------+----------+----------
      1 | Pear   |        1 | f
      2 | Apple  |        3 | t
      3 | Orange |        2 | t
      4 | Banana |        4 | t
    (4 rows)
    


    1. 接続されたユーザーをOracle10gデータベーススキーマから削除する

    2. SQLServerのforループの構文

    3. 挿入中にC#でSQLの一意の制約違反をキャッチするための最良の方法

    4. SqlDataAdapter.Fillメソッドが遅い