Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / PostgreSQL Новый топик    Ответить
 Partial Unique defferable  [new]
fsmoke
Member

Откуда:
Сообщений: 2
Как, сделать подобную штуку

Допустим есть таблица

CREATE TABLE public.tree123
(
id uuid NOT NULL,
parent uuid,
"order" integer NOT NULL,
CONSTRAINT tree123_pkey PRIMARY KEY (id),
CONSTRAINT tree123_check_parent FOREIGN KEY (parent)
REFERENCES public.tree123 (id) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE NO ACTION
)

Вопрос:
Как сделать уникальный "order" в пределах одного родителя(parent ) ?

Если я пишу так, всё работает, но только если parent не null

CONSTRAINT tree123_parent_order_key UNIQUE (parent, "order") DEFERRABLE


Если parent == null, то данный констрейнт не работает - погуглил нашел что можно сделать partial index

CREATE UNIQUE INDEX tree123_parent_null_order_idx
    ON public.tree123 USING btree
    (order)
    TABLESPACE pg_default   WHERE parent IS NULL
;


Но его нельзя сделать DEFERRABLE.

Соответсвенно когда мне нужно сделать так
UPDATE tree123 SET "order" = CASE "order" 
                      WHEN 1 THEN 2 
                      WHEN 2 THEN 1
                      ELSE "order"
                      END
 WHERE "order" IN(1, 2) and parent is not null;


это работает, а так нет :

UPDATE tree123 SET "order" = CASE "order" 
                      WHEN 1 THEN 2 
                      WHEN 2 THEN 1
                      ELSE "order"
                      END
 WHERE "order" IN(1, 2) and parent is null;


PS

PSQL 9.6
4 окт 17, 18:24    [20843225]     Ответить | Цитировать Сообщить модератору
 Re: Partial Unique defferable  [new]
LeXa NalBat
Member

Откуда: Москва
Сообщений: 2883
проверьте, сейчас сочинил

exclude ((coalesce(parent, uuid_nil())) with =, "order" with =) deferrable

+
rollback;

begin;

create table tree(
    id uuid not null,
    parent uuid,
    "order" integer not null,
    primary key(id),
    foreign key(parent) references tree,
    exclude ((coalesce(parent, uuid_nil())) with =, "order" with =) deferrable
);

with parent as(
    select uuid_generate_v4() as id
    , row_number() over() as rn
    from generate_series(1, 5)
), child as (
    select uuid_generate_v4() as id
    , parent.id as parent_id
    , row_number() over(partition by parent.id) as rn
    from parent, generate_series(1, 5)
) insert into tree(id, parent, "order") 
    select id, null, rn from parent
    union all
    select id, parent_id, rn from child;

update tree set "order" = 3 - "order" where "order" in(1, 2);

-- commit;
5 окт 17, 13:56    [20845358]     Ответить | Цитировать Сообщить модератору
 Re: Partial Unique defferable  [new]
fsmoke
Member

Откуда:
Сообщений: 2
Да работает всё супер, СПАСИБО
9 окт 17, 11:35    [20853898]     Ответить | Цитировать Сообщить модератору
Все форумы / PostgreSQL Ответить