Таблица пользователей для многих таблиц для входа - PullRequest
0 голосов
/ 02 мая 2020

Я пытаюсь построить систему управления школой, и у меня возникают проблемы при разработке оптимальной структуры базы данных. У меня есть таблицы для студентов, сотрудников и пользователей для входа в систему. Таблица пользователей будет содержать только регистрационную информацию (userNumber, пароль), а студенты и персонал будут содержать личную информацию. Я разделил студентов и сотрудников, потому что они содержат разные личные данные. Но у них обоих есть userNumber.

users(
id,
userNumber,
password
)

students(
id,
studentNumber,
name,
age
)

staff(
id,
staffNumber,
name,
age,
salary,
dateOfHiring,
staffType
)

Допустим, я вошел в систему с userNumber 98242, как дать системе знать, где мне искать, в таблице учеников или в таблице персонала?

Я хотел бы получить некоторые рекомендации по структурам базы данных.

Ответы [ 4 ]

0 голосов
/ 02 мая 2020

Хотя для студентов и сотрудников есть только несколько отдельных столбцов, я бы сказал, что все просто:

CREATE TABLE person (
  person_id int GENERATED ALWAYS AS IDENTITY PRIMARY KEY
, name      text
, birthday  date  -- never age! bitrots in no time
, student_number int
, staff_number int
, salary       numeric
, hired_at     date
, staff_type   text
, CONSTRAINT one_role_max CHECK (student_number IS NULL
                              OR (staff_number, salary, hired_at, staff_type) IS NULL)
, CONSTRAINT one_role_min CHECK (student_number IS NOT NULL
                              OR (staff_number, salary, hired_at, staff_type) IS NOT NULL)
);

CREATE TABLE users (
  user_number int GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY
, person_id   int NOT NULL REFERENCES person
, password    text -- encrypted !
);

Таким образом, один человек может иметь 0-n учетных записей пользователей - это типичная реальность. Вы можете ограничиться одной учетной записью на человека, добавив UNIQUE (person_id) к таблице users.

Ограничение CHECK one_role_max требует, чтобы столбцы учеников или столбцы сотрудников оставались пустыми.
CHECK ограничение one_role_min обеспечивает, что хотя бы один из них должен иметь какие-либо значения.
Адаптировать то, что должно / может быть заполнено, к вашим потребностям. Выражения работают отлично для текущего дизайна. См .:

Хотя это строго «или / или», и единственный столбец студента - student_number, этот запрос отвечает на ваш вопрос:

SELECT CASE WHEN student_number IS NULL THEN 'staff' ELSE 'student' END AS user_role
FROM   person
WHERE  person_id = (SELECT person_id FROM users WHERE user_number = 98242);

Или удалите одно или оба ограничения CHECK, чтобы разрешить одному и тому же человеку учиться и персоналу, или ни одному. Адаптируйте вышеуказанный запрос соответствующим образом.

Вы могли бы использовать наследование для этого (как демонстрирует Абелисто), но я бы предпочел держаться от него подальше. Когда-то была идея объектно-реляционной СУБД. Но сообщество в значительной степени продвинулось. Это работает, но с предостережениями . Разделение раньше было основным вариантом использования. Но декларативное разбиение в Postgres 10 в основном заменило реализацию на основе наследования. Интерес к нему уже не слишком велик.

А как насчет всех этих пустых столбцов? Я трачу там много места? Противоположный случай. Объем диска не станет намного меньше, чем этот. НУЛЕВОЕ хранилище очень дешево. См .:

0 голосов
/ 02 мая 2020

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

Тогда ваш запрос может выглядеть примерно так:

SELECT users.id as user_id, students.id, staff.id FROM users 
LEFT JOIN students ON users.id = students.id
LEFT JOIN staff ON users.id = staff.id
WHERE id = 98242
0 голосов
/ 02 мая 2020

Наследование:

create table persons (
  id,
  name,
  age
);

create table users (
  number,
  password
) inherits (persons);

create table students (
) inherits (users);

create table stuff (
  salary,
  dateOfHiring,
  staffType
) inherits (users);

Схематически, как-то так. Используя tableoid системный столбец , вы можете узнать происхождение конкретной строки:

select
  *,
  tableoid::regclass -- Prints the origin table name (users, students, stuff, ...)
from users
where number = 98242;
0 голосов
/ 02 мая 2020

просто добавьте столбец userType в users таблицу

enter image description here

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