Лучший способ создать уникальный номер для каждого отношения многие ко многим - PullRequest
0 голосов
/ 19 февраля 2009

У меня есть таблица студентов и таблица курсов, которые связаны через промежуточную таблицу для создания отношения «многие ко многим» (т. Е. Студент может записаться на несколько курсов, а курс может иметь несколько студентов). Проблема в том, что клиент хочет получить уникальный идентификатор студента для каждого курса. Например:

rowid Course Student      ID (calculated)
1     A      Ben          1
2     A      Alex         2
3     A      Luis         3
4     B      Alex         1
5     B      Gail         2
6     B      Steve        3

Идентификаторы должны быть пронумерованы от 1, и у студента может быть другой идентификатор для другого курса (например, у Алекса ID = 2 для курса A, но ID = 1 для курса B). Как только ID назначен, он фиксируется и не может измениться. Я реализовал решение, упорядочив строку rowid сквозной таблицы «SELECT Student from table WHERE Course = A ORDER BY rowid», а затем вернув число на основе порядка результатов.

Проблема с этим решением состоит в том, что если студент покидает курс (удаляется из таблицы), номера других студентов изменятся. Может кто-нибудь порекомендовать лучший способ? Если это имеет значение, я использую PostgreSQL и Django. Вот что я подумала:

  • Создание столбца для идентификатора вместо его расчета. Когда создаются новые отношения с присвоением идентификатора на основе максимального (id) +1 студентов в курсе
  • Добавление столбца «отключен» и установка его «Истина», когда студент покидает курс. Это потребовало бы изменения всего моего кода, чтобы убедиться, что используются только активные студенты

Я думаю, что первое решение лучше, но есть ли более «ориентированный на базу данных способ», где база данных может рассчитать это для меня автоматически?

Ответы [ 4 ]

2 голосов
/ 19 февраля 2009

Если вы хотите иметь стабильные ID, вам определенно нужно хранить их в таблице.

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

Если у вас есть параллельный доступ к вашим таблицам, не используйте MAX(id), так как два запроса могут выбрать один и тот же MAX(id) перед вставкой в ​​таблицу.

Вместо этого создайте отдельную таблицу, которая будет использоваться как sequence, заблокируйте строку каждого курса с помощью SELECT FOR UPDATE, затем вставьте ID нового студента и обновите строку новым ID в одной транзакции, как это:

Courses:

Name     NextID
-------  ---------
Math     101
Physics  201

Attendants:

Student Course   Id
------- ------   ----
Smith   Math     99
Jones   Math     100
Smith   Physics  200
BEGIN TRANSACTION;

SELECT NextID
INTO   @NewID
FROM   Courses
WHERE  Name = 'Math'
FOR UPDATE;

INSERT
INTO Attendants (Student, Course, Id)
VALUES ('Doe', 'Math', @NewID);

UPDATE
  Courses
SET NextID = @NewID + 1
WHERE Course = 'Math';

COMMIT;
0 голосов
/ 19 февраля 2009

Я думаю, что есть две концепции, которые вам нужны, чтобы помочь вам здесь.

  1. Последовательности , где база данных автоматически получает для вас следующее значение для идентификатора
  2. Составные ключи , где можно объединить несколько столбцов для создания первичного ключа таблицы.

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

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

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

Вместо этого создается столбец для идентификатора рассчитать это. Когда новый отношения создаются назначением ID на основе макс (id) +1 из студенты на курсе

Вот как я это сделаю. Нет смысла его вычислять. И идентификатор не должен меняться только потому, что кто-то выпал.

Добавление столбца «отключено» и настройка Это правда, когда студент покидает курс.

Да, это была бы хорошая идея. Еще один создает другую таблицу с той же структурой, где вы будете хранить пропущенных студентов. Тогда, конечно, вам нужно будет выбрать max (id) из объединения этих двух таблиц.

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

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

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