2009-06-28 18 views
11

Я разрабатываю базу данных для организации, которая имеет несколько «типов» пользователей. Сначала я создал только одну пользовательскую таблицу. Однако, хотя все пользователи имеют общую информацию (имя, фамилия, имя пользователя, пароль и т. Д.), Для каждого типа пользователя требуется одно или два дополнительных поля, которые не применимы ко всем пользователям. Хотя я могу создать эти дополнительные поля и установить их как NULL, я не хочу этого делать, поскольку поля являются внешними ключами, и это вызывает проблемы для меня.MySQL Вопрос. Как обрабатывать несколько типов пользователей - одну таблицу или несколько?

Как обычно обрабатывается эта ситуация?

Спасибо!

ответ

9

Ваши инстинкты, чтобы не создавать большой стол с большим количеством NULLS прямо на. Это плохая идея, с точки зрения хранения/восстановления/обслуживания, а также точки проверки данных (подробнее об этом позже).

Два наиболее распространенные approcaches:

1) Иметь пользовательскую таблицу со всеми общими полями в нем, в том числе поля «UserType». Затем добавьте отдельную таблицу для каждого типа пользователя, содержащего дополнительные поля. Все пользователи имеют строку в таблице пользователей и одну или несколько таблиц конкретных типов пользователей. Это наиболее нормализованный и наиболее эффективный способ хранения и быстрого входа в систему. Это также позволяет использовать ограничения и внешние ключи, чтобы обеспечить доступность всей необходимой информации для каждого типа пользователя.

2) У пользователя есть таблица со всеми общими полями. У другой таблицы есть что-то вроде UserAttributes, у которого есть поля для userid, key и value. Любые дополнительные метаданные для конкретного пользователя могут быть сохранены здесь. Это имеет то преимущество, что не требуется, чтобы любое администрирование базы данных добавляло новые типы пользователей или метаданные, которые должны храниться для каждого типа пользователя. Однако он не позволяет выполнять проверку данных на уровне БД.

+0

Спасибо, dj_segfault. Я пошел с вашей опцией # 1 и создал пользовательскую таблицу с общими полями и поле userType, на которое ссылаются другие, более «конкретные» пользовательские таблицы. NULLS определенно вызывали головные боли, я рад, что избавился от них сейчас! – littleK

+0

исправьте меня, если я ошибаюсь (это случается очень много), но если кто-то должен хранить свои данные таким образом, чтобы общие поля находились на уровне «пользователя», например, fname, lname, email, pw ... и так далее , Невозможно было бы получить более конкретную информацию пользователя с одним запросом? Для получения более конкретной информации всегда требуется второй запрос, основанный на типе usertype. – ackerchez

+0

@ackerchez Sure есть. Все, что вам нужно сделать, чтобы получить всю информацию, - это внутреннее соединение всех пользовательских таблиц пользовательского типа с основной пользовательской таблицей любым вашим UID. Столбцы для таблиц, которые не для этого типа пользователя, будут пустыми. –

4

Реляционная модель как таковая не поддерживает «наследование», что может помочь решить эту проблему (хотя некоторые механизмы БД, такие как PostgreSQL, поддерживают наследование).

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

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

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

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

Возможно, что некоторая денормализация, которая может быть полезной здесь, представляет собой столбец перечисления в таблице пользователей, указывающий «основную» или «единственную» роль каждого конкретного использования (он может быть обнуляемым и, возможно, равномерно пустым в начале, если я был достаточно настойчив, чтобы иметь его с самого начала ...; -) ... но я, скорее всего, буду ждать его добавления, если и когда производительность некоторых конкретных запросов потребует его как конкретной оптимизации, а не для разработки схемы таким образом с самого начала (обратите внимание, что это ключевая причина никогда не использовать SELECT * FROM в ваших запросах - если вы добавите ALTER TABLE, чтобы добавить столбец, то SELECT * - это один бит, который сломался бы! -).

+0

Alex, спасибо большое за ваш ответ, это действительно помогло мне. Я сделал то, что вы предлагали, и создал таблицу с общими полями, а также отдельные таблицы для других не общих полей для каждого типа пользователя. Я также добавил столбец перечисления роли в таблице пользователей. Спасибо! – littleK

1

Это известный вопрос о нормализации.

Загляните в эту статью или другие подобные ей, чтобы попытаться найти ответ, соответствующий потребностям бизнеса.

To normalize or not to normalize

+0

Большое спасибо за статью, нашел ее очень полезной. У меня было так много вопросов по этой теме, и это ответствовало на многие из них. Спасибо! – littleK

+0

Идет, чтобы дать +1, но ссылка больше не работает. Вы хотите обновить его? –

+0

@Gabriel Wow - Я не знаю, работала ли она когда-либо. Я обновил его до нужной статьи – Brian

0

Вы не сказали, если вы используете язык высокого уровня, так что я просто приведу общий пример с DB-как, например:

Проектирование баз данных трудно. Итак, это будет быстрый и простой ответ.

Ваш вопрос является основным вопросом о связях данных и дизайне базы данных. Изучите некоторые основные руководства по использованию, чтобы помочь в этом ответе. Это может помочь подумать о том, как группируется ваша информация, и связать «назад» с основным набором (таблицей) с другими наборами (таблицами).

Итак, пользователи пользователей - вот ваш стол. Он должен содержать основные, общие элементы (столбцы) данных, связанных с пользователем.

Затем этот другой набор информации (например, разрешения или что-то еще) является другой таблицей.

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

например, вид таблицы «разрешение» для пользователей:

- integer "id"  <--- unique, index column, auto-increment 
    - integer "user_id" <--- this is which user this belongs 
    - ... 
    - Boolean "can_write"   <--- example data column 
    - Boolean "can_read"   <--- example data column 
    - Boolean "can_reboot_system" <--- example data column 
    - etc, whatever you want 

Итак, вы можете «SELECT * FROM user_table WHERE first_name = 'joe' (или такой) ... чтобы получить пользователя. Там я надеюсь, что у вас есть какое-то значение« id »для идентификации этой строки.

Теперь просто сделайте «SELECT * FROM разрешений WHERE user_id =« nnnn »(независимо от того, какой идентификатор пользователя).

Если пользователь имеет только 1 набор разрешений, то вы можете просто иметь этот user_id без дополнительного столбца «id».

+0

joej- Я никогда не думал об объявлении разрешений на уровне базы данных. Конечно, это хорошая идея. Прямо сейчас, у меня просто есть таблица «роль», которая ссылается на пользователя (а затем я применяю эту роль к php-коду). Мне нравится ваша идея, хотя я планирую изучить ее больше. Спасибо! – littleK