Postgresql

如何在同一個表的列之間定義一對多約束?

  • March 5, 2021

我正在 PostgreSQL 中創建一個 IDs 表來表示多個外部 ID 之間的關係 - 稱它們為a,bc.

我碰巧知道外國ID之間有一對多的關係:

a 1..* b b 1..* c

a我想將它們表示為一個表(見下文),但在& b、 & 和 之間b強制執行一對多不變數c

那可能嗎?

範例:以下插入是非法的:

給定以下合法表格:

這必須由 完成,因為它對於約束TRIGGER來說太複雜了CHEKC

對於更新,您需要類似的觸發器/功能

CREATE TABLE tabl1
    ("pk" varchar(5), "a" varchar(6), "b" varchar(6), "c" varchar(6))
;
    
INSERT INTO tabl1
    ("pk", "a", "b", "c")
VALUES
    ('p1', 'a1', 'b11', 'c111'),
    ('p2', 'a1', 'b11', 'c112'),
    ('p3', 'a1', 'b12', 'c121'),
    ('p4', 'a1', 'b12', 'c122'),
    ('p5', 'a2', 'b21', 'c211'),
    ('p6', 'a2', 'b21', 'c212'),
    ('p7', 'a2', 'b22', 'c221'),
    ('p8', 'a2', 'b22', 'c222'),
    ('p9', NULL, 'b31', 'c311'),
    ('p10', 'a3', NULL, 'c312'),
    ('p11', 'a3', 'b31', NULL),
    ('p12', NULL, NULL, 'c314'),
    ('p13', NULL, 'b31', NULL),
    ('p14', 'a3', NULL, NULL)
;
CREATE OR REPLACE FUNCTION check_insert()
RETURNS TRIGGER AS $$
   BEGIN
   IF EXISTS(SELECT 1 FROM tabl1 WHERE "c" = NEW."c" AND "b" = NEW."b" ) then
       raise EXCEPTION 'The column %  already  with %',NEW."c",NEW."b";
   ELSIF EXISTS(SELECT 1 FROM tabl1 WHERE "a" <> NEW."a" AND "b" = NEW."b" ) then
           raise EXCEPTION 'The column %  already  has already a column',NEW."b";
   END IF;
   RETURN NEW;
   END;
$$ LANGUAGE plpgsql;
CREATE  TRIGGER trigger_name BEFORE
 INSERT
ON tabl1
FOR EACH ROW
EXECUTE PROCEDURE check_insert();
INSERT INTO tabl1
    ("pk", "a", "b", "c")
VALUES
    ('p15', 'a1', 'b11', 'c111')
錯誤:列 c111 已包含 b11

上下文: PL/pgSQL 函式 check_insert() 第 4 行,位於 RAISE

INSERT INTO tabl1
    ("pk", "a", "b", "c")
VALUES
('p16' , 'a1'   , 'b21'  , 'c213' )
錯誤:b21 列已經有一個列

上下文: PL/pgSQL 函式 check_insert() 第 6 行,位於 RAISE

INSERT INTO tabl1
    ("pk", "a", "b", "c")
VALUES
('p17',   'a2',   'b11'   ,'c214')
錯誤:b11 列已經有一個列

上下文: PL/pgSQL 函式 check_insert() 第 6 行,位於 RAISE

SELECT * FROM tabl1
PK | 一個 | 乙 | C 
:-- | :--- | :--- | :---
p1 | a1 | b11 | c111
p2 | a1 | b11 | c112
p3 | a1 | b12 | c121
p4 | a1 | b12 | c122
p5 | a2 | b21 | c211
p6 | a2 | b21 | c212
p7 | a2 | b22 | c221
p8 | a2 | b22 | c222
p9 | *空*| b31 | c311
p10 | a3 | *空*| c312
p11 | a3 | b31 | *空*
p12 | *空*| *空*| c314
第 13 頁 | *空*| b31 | *空*
p14 | a3 | *空*| *空值*

db<>在這裡擺弄

引用自:https://dba.stackexchange.com/questions/286498