powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Как обеспечить частичную уникальность ?
25 сообщений из 98, страница 1 из 4
Как обеспечить частичную уникальность ?
    #39822114
Сисдба Мастеркеевич
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Всем привет.

Такая задача: есть пользователи, им выдаются некоторые бонусы. Пользователь может активировать бонус, т.е. у бонуса есть статус.
И есть нюанс - у каждого пользователя активным может быть только один бонус. Далее активный бонус либо отменяется, либо используется, т.е. в дальнейшем статус его изменяется либо по решению пользователя, либо после срабатываения некоторых условий.

Как сделать такое ограничение в базе ?

Идеально быть бы сделать partial index , как у конкурентов:
Код: sql
1.
create unique index some_index on bonus (user_id) where status = 'active'



Но у нас такого нет, увы.
Есть CORE-3384 , но там как-то бесперспективно всё.

Просматривается 2 некрасивых решения:
1. Завести отдельную табличку active_bonuses, обеспечивать уникальность с ее помощью.
2. Сделать вычисляемое (в триггере) поле uniq_status, что-то типа case when status = 'active' then status end, и повесить уник на (user_id, uniq_status)

Оба решения не нравятся, потому что требуют заводить какие-то дополнительные объекты, являющиеся, по сути, костылями.
...
Рейтинг: 0 / 0
Как обеспечить частичную уникальность ?
    #39822144
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сисдба Мастеркеевич,

можно попробовать уникальный индекс по выражению, не знаю будет ли работать

Код: sql
1.
2.
CREATE UNIQUE INDEX UNQ_BONUS_USER 
ON BONUS COMPUTED BY (CASE WHEN STATUS = 'active' THEN user_id END);
...
Рейтинг: 0 / 0
Как обеспечить частичную уникальность ?
    #39822145
hvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сисдба Мастеркеевич,

Оно ?
Код: sql
1.
create unique index some_index on bonus computed by (case when status = 'active' then user_id end)
...
Рейтинг: 0 / 0
Как обеспечить частичную уникальность ?
    #39822147
hvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денис,

:)
...
Рейтинг: 0 / 0
Как обеспечить частичную уникальность ?
    #39822167
Сисдба Мастеркеевич
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Точно, есть же computed by. Забыл. Спасибо :)
...
Рейтинг: 0 / 0
Как обеспечить частичную уникальность ?
    #39822184
WildSery
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сисдба Мастеркеевич,

А что, история статусов никому не интересна?
...
Рейтинг: 0 / 0
Как обеспечить частичную уникальность ?
    #39822301
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Создаешь таблицу с двумя полями - "user_id" и "bonus_id" по полю "user_id" делаешь первичный ключ, оба поля внешним ключом к соответствующим справочникам пользователей и бонусов И ВСЁ! Больше тебе ничего не надо, потому как одному пользователю ты сможешь привязать лишь один бонус. Ну и, как уже упомянул ДикийСерж, хорошо бы добавить историю, то есть в первичный ключ добавить ещё и TIMESTAMP.
...
Рейтинг: 0 / 0
Как обеспечить частичную уникальность ?
    #39822309
Мимопроходящий
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
04.06.2019 14:12, rdb_dev пишет:
> в первичный ключ добавить ещё и TIMESTAMP.

и положение звёзд на небосводе.
первичный ключ в который добавлен ещё и TIMESTAMP вырождается в банальный пшшшшшик.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как обеспечить частичную уникальность ?
    #39822337
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мимопроходящийпервичный ключ в который добавлен ещё и TIMESTAMP вырождается в банальный пшшшшшик.Похоже, сегодня за обедом ты съел что-то несвежее...
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
CREATE TABLE "active_bonus"
(
    "tmstmp"    TMSTMP NOT NULL,
    "user_id"   ID NOT NULL,
    "bonus_id"  ID NOT NULL,
  CONSTRAINT "active_bonus__pk" PRIMARY KEY ("user_id", "tmstmp")
);

INSERT INTO "active_bonus" ("tmstmp", "user_id", "bonus_id")
        SELECT CURRENT_TIMESTAMP-10, 1, 4 FROM oneRow
  UNION SELECT CURRENT_TIMESTAMP-2, 2, 3 FROM oneRow
  UNION SELECT CURRENT_TIMESTAMP-5, 2, 8 FROM oneRow
  UNION SELECT CURRENT_TIMESTAMP-20, 3, 8 FROM oneRow
  UNION SELECT CURRENT_TIMESTAMP-3, 3, 3 FROM oneRow
  UNION SELECT CURRENT_TIMESTAMP-9, 3, 4 FROM oneRow;

WITH "last" AS
(
  SELECT "user_id", Max("tmstmp") AS "tmstmp"
    FROM "active_bonus"
    GROUP BY "user_id"
)
SELECT ab."user_id", ab."bonus_id", ab."tmstmp"
  FROM "active_bonus" ab
    INNER JOIN "last" l
      ON l."user_id" = ab."user_id" AND l."tmstmp" = ab."tmstmp"
...
Рейтинг: 0 / 0
Как обеспечить частичную уникальность ?
    #39822343
hvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Определись уже, как
rdb_devкак одному пользователю ты сможешь привязать лишь один бонус
связано с
rdb_dev
Код: plsql
1.
2.
3.
INSERT INTO "active_bonus" ("tmstmp", "user_id", "bonus_id")
      SELECT CURRENT_TIMESTAMP-2, 2, 3 FROM oneRow
  UNION SELECT CURRENT_TIMESTAMP-5, 2, 8 FROM oneRow
...
Рейтинг: 0 / 0
Как обеспечить частичную уникальность ?
    #39822347
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hvlad, последний по времени бонус и есть активный.
...
Рейтинг: 0 / 0
Как обеспечить частичную уникальность ?
    #39822353
hvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_dev,

тему топика читал ? Прочитай.
...
Рейтинг: 0 / 0
Как обеспечить частичную уникальность ?
    #39822357
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hvlad, и чо? Там нагородили огород с полем "status", которое прекрасно и в соответствии с требованиями заменяется таблицей, т.е. последний по времени бонус пользователя имеет статус активный, остальные - неактивный. Если кого-то не устраивает представление данных, можно построить вьюху с вычисляемым значением поля "status". В чём проблема?
...
Рейтинг: 0 / 0
Как обеспечить частичную уникальность ?
    #39822375
hvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_devВ чём проблема?Всё прекрасно, фантазируй дальше, я - пас
...
Рейтинг: 0 / 0
Как обеспечить частичную уникальность ?
    #39822398
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hvladrdb_devВ чём проблема?Всё прекрасно, фантазируй дальше, я - пасДа ёлки-палки!...
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
CREATE OR ALTER VIEW "bonus"
AS
WITH "last" AS
(
  SELECT "user_id", Max("tmstmp") AS "tmstmp"
    FROM "active_bonus"
    GROUP BY "user_id"
)
SELECT ab."user_id", ab."bonus_id",
    Iif(l."user_id" IS NULL, _ASCII 'inactive', _ASCII 'active') AS "status"
  FROM "active_bonus" ab
    LEFT JOIN "last" l
      ON l."user_id" = ab."user_id" AND l."tmstmp" = ab."tmstmp"
...
Рейтинг: 0 / 0
Как обеспечить частичную уникальность ?
    #39822410
Мимопроходящий
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
04.06.2019 15:16, rdb_dev пишет:
> CONSTRAINT "active_bonus__pk" PRIMARY KEY ("user_id", "tmstmp")

синтаксический нонсенс.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как обеспечить частичную уникальность ?
    #39822418
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мимопроходящий04.06.2019 15:16, rdb_dev пишет:
> CONSTRAINT "active_bonus__pk" PRIMARY KEY ("user_id", "tmstmp")

синтаксический нонсенс.Неужели? С каких пор у нас запрет на составные первичные ключи? Или для тебя первичный ключ, это исключительно суррогат?
...
Рейтинг: 0 / 0
Как обеспечить частичную уникальность ?
    #39822428
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_dev,

запрета нет. Есть вопрос целесообразности и удобства. Составные как и натуральные PK не удобны априори, если уж надо сделать такое ограничение, то обычно ставят UNIQUE в довесок к суррогатному PK
...
Рейтинг: 0 / 0
Как обеспечить частичную уникальность ?
    #39822433
hvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_devДа ёлки-палки!...Ты забыл цель - обеспечить уникальность.
Ты её не обеспечиваешь.
Вместо этого продаёшь историю, о которой никто не просил.
Направь свою энергию на что-нить полезное уже

PS И - да - таймстамп в PK - это обычно от глупости и не понимания сути задачи.
Примерно как и double precision в там же.
Не всегда, но чаще всего.
...
Рейтинг: 0 / 0
Как обеспечить частичную уникальность ?
    #39822434
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денисrdb_dev,

запрета нет. Есть вопрос целесообразности и удобства. Составные как и натуральные PK не удобны априори, если уж надо сделать такое ограничение, то обычно ставят UNIQUE в довесок к суррогатному PKСоставные ПК не удобны, когда таблица не является конечно в иерархии отношений, а если таблица конечна, вполне можно воспользоваться принципом бритвы Оккама и не порождать сущности без надобности.
...
Рейтинг: 0 / 0
Как обеспечить частичную уникальность ?
    #39822435
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hvladПримерно как и double precision в там же.

Timestamp хотя бы целый в отличии от.

PS: Тупо добавить поле "текущий бонус" в таблицу пользователей не предлагали или я не заметил?
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как обеспечить частичную уникальность ?
    #39822456
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hvladТы забыл цель - обеспечить уникальность.
Ты её не обеспечиваешь.Именно упомянутую уникальность я и обеспечиваю!
Условие таково - "у пользователя не может быть более двух активных бонусов одномоментно" и составной ПК по полям "user_id"+"tmstmp" вполне обеспечивает это условие, так как ты не сможешь для одного и того же пользователя добавить в таблицу две записи с разными бонусами, но с одним и тем же штампом времени.
...
Рейтинг: 0 / 0
Как обеспечить частичную уникальность ?
    #39822466
hvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_dev,

ну да, не сможешь. У тебя мало опыта реальной работы реальных юзеров.
В реальных приложениях.
...
Рейтинг: 0 / 0
Как обеспечить частичную уникальность ?
    #39822467
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hvlad, ты хочешь сказать, что для таблицы:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
CREATE TABLE "active_bonus"
(
    "tmstmp"    TMSTMP NOT NULL,
    "user_id"   ID NOT NULL,
    "bonus_id"  ID NOT NULL,
  CONSTRAINT "active_bonus__pk" PRIMARY KEY ("user_id", "tmstmp")
);

Сервер FirebirdSQL не обеспечить уникальность составного ПК? Тогда тут дело совсем не в пользователях...
...
Рейтинг: 0 / 0
Как обеспечить частичную уникальность ?
    #39822468
Мимопроходящий
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
04.06.2019 18:51, rdb_dev пишет:
> Сервер FirebirdSQL не обеспечить уникальность составного ПК?
> Тогда тут дело совсем не в пользователях...

угу.
тут дело в "дизайнере".
ибо уникальность именно ЭТОГО ключа не несёт никакой смысловой нагрузки.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
25 сообщений из 98, страница 1 из 4
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Как обеспечить частичную уникальность ?
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]