Есть таблица:
CREATE TABLE link
(
id serial NOT NULL,
"group" character varying(250),
portid1 integer NOT NULL,
portid2 integer NOT NULL,
active boolean NOT NULL DEFAULT true,
CONSTRAINT link_pkey PRIMARY KEY (id),
CONSTRAINT unique_portid1 CHECK (check_link(portid1, id)),
CONSTRAINT unique_portid2 CHECK (check_link(portid2, id))
)
CREATE OR REPLACE FUNCTION check_link(portid integer, linkid integer)
RETURNS boolean AS
$BODY$
DECLARE
i int;
BEGIN
IF EXISTS (SELECT * FROM link
WHERE (portid1 = portid or portid2=portid) and id!=linkid) THEN
RETURN false;
END IF;
RETURN true;
END
Смысл этого CHECK CONSTRAINT в том, что в таблице значения в колноках portid1 и portid2 должны быть различны, то есть если в колонке portid1 уже присутствует какое-то значение, то оно уже не может появится ни в колонке portid1, ни в колонке portid2, аналогично и для portid2.
Я написал данный constraint, проверил его с помощью простых INSERT и UPDATE - работает. Однако, сегодня обнаружил в таблице вот такой набор записей:
select * from link where portid1 = 74581 or portid2=74581;
id | group | portid1 | portid2 | active
-------+-------+---------+---------+--------
76628 | | 113945 | 74581 | t
76629 | | 113945 | 74581 | t
76630 | | 113945 | 74581 | t
76632 | | 113945 | 74581 | t
76633 | | 113945 | 74581 | t
76634 | | 74581 | 113945 | t
76645 | | 113945 | 74581 | t
(7 rows)
Пробовал сделать Insert с этими же portid, constraint отрабатывает, не получается вставить запись. Попробовал удалить constraint, повесить заново - не получилось, то есть никто не мог удалить constraint, вставить записи и снова повесить. Как оказалось такая ситуация не единичная.
Подскажите, как такое могло получится? Потому что я использую SELECT в constraint? И как сделать правильно?