0x01AA
Вы находитесь на хорошем пути, и для первой работы с RDB вы сделали это довольно хорошо. Но есть некоторые моменты, о которых вам нужно подумать. признать и некоторые последствия.
Имейте в виду, что невозможно дать вам окончательный ответ, в порядке ли ваш макет или нет, не зная больше о вашей конечной цели. Но можно выделить некоторые моменты, чтобы дать вам представление о последствиях дизайна. Итак, давайте пройдемся по нему, таблица за таблицей.Для следующего Я предполагаю, что все поля *ID
имейте тип данных int.
[Пользователи]
UID (pri)
Вероятно, внутренний автоматически сгенерированный ключ, определенный как первичный, используемый для управления реализациями. Обычно конечный пользователь никогда не вступает в контакт с этим значением. Кстати, широко используемая техника. Я тоже всегда так делаю.
Username
На данный момент никакой контстринт не распознается из данного вами источника. Но подумайте о том, какая путаница возникает, если два человека будут использовать одно и то же имя пользователя.
- > Так что, скорее всего, вы примените уникальное ограничение для UserName
.
Обсуждение:
Как вы можете видеть, введение "внутреннего числового первичного элемента" заставит нас ввести также что-то вроде "пользовательского первичного элемента", что приведет к одним индексом больше Не беспокойтесь об этом, это действительно широко используемая техника.
Примечание:
Если вы не обращаете внимания на техническое решение и дизайн макета вашей базы данных строго основываясь на теории, то" имя пользователя " будет реальным первичным ключом. С тем следствием, что и внешние ключи становятся однотипными...
[Архив]
FID (pri)
Же жидкость выше, ОК.
Filename
То же самое, что и выше, с именем пользователя, но, возможно, не так критично. Лично я бы также применил уникальное ограничение для Filename>
[Пользовательские файлы]
Давайте сначала посмотрим на более легкую часть:
UserFiles.UID
должен быть определен как внешний ключ к Users.UID
Здесь вы должны подумать о том, чтобы также включить "on DELETE CASCADE" в определение внешнего ключа. Это означает, что в случае удаления пользователя все записи в UserFiles также будут удалены для соответствующего пользователя.
"ON DELETE CASCADE" - это круто, нам не нужно беспокоиться о том, чтобы удалить детали в пользовательских файлах. Хммм.... действительно холодный?
В какой-то ситуации это здорово, но здесь ли это также для вашего макета? Только вы можете это решить. В чем смысл: если вы разрешаете / должны удалить пользователя, это означает, что вам нужно удалить файлы пользователей (в случае, если вы делаете файлы пользователей.UID внешний ключ). Но, наконец, это означает также удаление соответствующих пользовательских файлов удаляет также информацию о том, какие файлы были загружены каким пользователем Опять же, вам решать, сможете ли вы жить с этим.
UserFiles.FID
должен быть определен как внешний ключ к Files.FID
Не применяйте "on DELETE CASCADE" для этого внешнего ключа, иначе все файлы, связанные с удаленным пользователем, также будут удалены, если они не используются другими пользователями ;)
Теперь самое трудное:
На данный момент Вы определили последовательность из трех полей UserFilesID, UID, FID
в качестве первичного ключа для пользовательских файлов. Но было ли это действительно первичным?
V1.) на первый взгляд это должно быть UID, FID
Но таким образом пользователь может только загрузить или загрузить файл.
V2.) давайте позволим пользователю загрузить файл, а затем загрузить его. Это означает, что первичный должен быть похож UID,FID,Operation
Но вот так пользователь может скачать файл только один раз...
- > V1 и V2 не имеют смысла, давайте забудем о них.
Ну и что теперь? Для этого нам нужно определить, что мы позволяем пользователю делать.
а) может ли пользователь загрузить файл более одного раза?
Б) может ли пользователь загрузить файл более одного раза?
Ответы на вышеприведенный вопрос помогут решить, как идти дальше. Итак, я бы решил так:
а) да, пользователь может загрузить файл несколько раз. Но тогда нам нужно еще одно поле, чтобы сделать первичное, то есть счетчик или дата-время.
б) один и тот же файл не может быть загружен более одного раза с одним и тем же именем файла.
- > Остановимся здесь... эти два аспекта мы не будем связывать с вопросом о первичном ключе для пользовательских файлов.
После всего вышесказанного я бы сделал UserFiles _at The moment_ вот так:
CRATE TABLE UserFiles
(
UserFilesID integer not null,
UID integer not null,
FID integer not null,
Operation nchar...,
LogDate datetime, // Information only
CONSTRAINT PK_UserFiles PRIMARY KEY (UserFilesID),
CONSTRAINT FK_UserFiles_Users FOREIGN KEY (UID) REFERENCES Users (UID)
ON DELETE CASCADE,
CONSTRAINT FK_UserFiles_Files FOREIGN KEY (FID) REFERENCES Files (FID)
)
Абстрактный:Q1: Is my DB design right?
Q2: Is this a correct logic? or what I should expect?
См. выше Обсуждение и некоторые детали, которые вам нужно решить.
Q3: How can I check if my design is correct? I'm thinking a select statement that would check the uploads of user with UID=22 and the result is files with FID = 10,11,12
Это один тест, потребуется еще. Спросите себя, что вы хотите показать, а затем сделайте SQL для этого, протестируйте его и сравните результат с ожидаемым.
Q4: What select statement should I use?
SELECT
Users.UID,
Users.UserName,
Users.RealName,
UserFiles.UserFilesID,
UserFiles.UID
UserFiles.FID
UserFiles.Operation,
Files.FileName,
Files.Description
FROM Users
LEFT JOIN UserFiles ON UserFiles.UID = Users.UID
LEFT JOIN Files ON Files.FID = UserFiles.FID
WHERE Users.UID = @UID
ORDER BY ....
Подсказка для ограничений внешнего ключа:
Проверьте с помощью выбранного вами SQL-сервера, создает ли определение внешнего ключа также для него неуникальный индекс. Это становится важным, когда ваша база данных становится большой. то есть MSSQL не создает индекс для ограничения внешнего ключа, и если у вас есть подробная таблица с сотнями тысяч записей, это обычно становится узким местом.
Удачи, и я надеюсь, что это поможет.