Как избежать дублирования регистрации в MySQL - PullRequest
0 голосов
/ 02 февраля 2009

Интересно, можно ли запретить пользователям вставлять дубликаты регистрационных записей? Например, какая-то команда зарегистрирована с 5.1.2009 по 31.12.2009. Затем кто-то регистрирует ту же команду на 5.2.2009 - 31.12.2009. Обычно end_date не является проблемой, но start_date не должно быть между существующими записями даты начала и окончания

CREATE TABLE IF NOT EXISTS `ejl_team_registration` (
  `id` int(11) NOT NULL auto_increment,
  `team_id` int(11) NOT NULL,
  `league_id` smallint(6) NOT NULL,
  `start_date` date NOT NULL,
  `end_date` date NOT NULL,
  PRIMARY KEY  (`team_id`,`league_id`,`start_date`),
  UNIQUE KEY `id` (`id`)
);

Ответы [ 4 ]

3 голосов
/ 02 февраля 2009

Я бы проверил это в коде программы, а не в базе данных.

1 голос
/ 03 февраля 2009

Это классическая проблема перекрытия времени. Допустим, вы хотите зарегистрировать определенную команду на период от A (дата_ начала) до B (дата_ конца).

Это НЕ должно быть разрешено в следующих случаях:

  1. та же команда уже зарегистрирована, так что зарегистрированный период полностью находится внутри периода A-B (start_date> = A и end_date <= B) </li>
  2. та же команда уже зарегистрирована в точке A (start_date <= A и end_date> = A)
  3. та же команда уже зарегистрирована в точке B (start_date <= B и end_date> = B)

В этих случаях регистрация может привести к совпадению времени. В любом другом это не так, поэтому вы можете зарегистрироваться.

В sql проверка будет:

select count(*) from ejl_team_registration
where (team_id=123 and league_id=45)
and ((start_date>=A and end_date<=B)
or (start_date<=A and end_date>=A)
or (start_date<=B and end_date>=B)
);

... с реальными значениями для team_id, league_id, A и B.

Если запрос возвращает что-либо, кроме 0, команда уже зарегистрирована, и повторная регистрация приведет к перекрытию времени.

Чтобы продемонстрировать это, давайте заполним таблицу:

insert into ejl_team_registration (id, team_id, league_id, start_date, end_date)
values (1, 123, 45, '2007-01-01', '2007-12-31')
, (2, 123, 45, '2008-01-01', '2008-12-31')
, (3, 123, 45, '20010-01-01', '2010-12-31');

Давайте проверим, можем ли мы зарегистрировать команду 123 на этапе 45 между '2009-02-03' и '2009-12-31':

select count(*) from ejl_team_registration
where (team_id=123 and league_id=45)
and ((start_date<='2009-02-03' and end_date>='2009-12-31')
or (start_date<='2009-03-31' and end_date>='2009-03-02')
or (start_date<='2009-12-31' and end_date>='2009-12-31')
);

Результат равен 0, поэтому мы можем свободно зарегистрироваться. Регистрация между например «2009-02-03» и «2011-12-31» были бы невозможны. Я оставлю проверять другие значения для вас в качестве практики.

PS: Вы упоминали, что дата окончания обычно не является проблемой. На самом деле это так, поскольку вставка записи с недопустимой датой окончания также может привести к перекрытию.

1 голос
/ 02 февраля 2009

Если вы хотите сделать это в базе данных, вы, вероятно, можете использовать триггер предварительной вставки , который не будет работать, если есть какие-либо конфликтующие записи.

0 голосов
/ 02 февраля 2009

Перед выполнением ВСТАВКИ выполните ВЫБОР, чтобы проверить.

SELECT COUNT(*) FROM `ejl_team_registration`
WHERE `team_id` = [[myTeamId]] AND `league_id` = [[myLeagueId]]
    AND `start_date` <= NOW()
    AND `end_date` >= NOW()

Если возвращается больше 0, не вставляйте.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...