Довольно много приложений требуют, чтобы записи в их таблицах имели статус, такой как «завершено», «черновик», «отменено». Каков наилучший способ хранения этих статусов? Чтобы проиллюстрировать то, к чему я клоню, приведу очень короткий пример.
У меня есть простое приложение для блога, и у каждого сообщения есть статус: опубликовано, черновик или ожидает рассмотрения.
На мой взгляд, есть два способа смоделировать это в базе данных.
- Таблица «Post» имеет текстовое поле, которое включает текст статуса.
- Таблица Post имеет поле состояния, которое содержит идентификатор записи в таблице PostStatus.
Пример блога здесь очень простой. Где может быть достаточно enum (если поддерживается). Однако я бы хотел, чтобы в ответах на этот вопрос учитывалось, что список статусов может измениться в любое время, чтобы можно было добавлять или удалять больше.
Кто-нибудь может объяснить преимущества / недостатки каждого?
Ура!
Мой первоначальный выбор заключается в том, что лучше использовать другую таблицу и искать состояние как лучшее для нормализации, и меня всегда учили, что нормализация хороша для баз данных
источник
Ответы:
Хранение статуса в качестве индекса в другой таблице является ненужным осложнением. Храните статус непосредственно в таблице в удобочитаемом виде. В коде приложения используйте константы или тип перечисления. Это приведет к упрощению кода приложения и упрощению отладки уровня данных.
Это не денормализует данные, оно просто меняет представление. Если база данных поддерживает перечисления напрямую, используйте это. В противном случае используйте ограничение для ограничения значений столбца. Вы будете иметь ограничение в любом случае: либо прямое ограничение на значения столбца, либо ограничение внешнего ключа.
Да, возможно, вам придется по-разному представлять статус различным пользователям. Это проблема представления, которая должна решаться на уровне представления, а не на уровне постоянства.
источник
Хранение текста статуса - это не очень хорошая идея, так как кто-то может решить, что вместо этого «завершить» следует называть «завершенным», а затем вам придется обновить базу данных, просмотреть программу, если кто-то жестко закодировал текст и т. Д.
Во многих программах я видел либо числовой код (1 = новый, 2 = черновик, 3 = при проверке, 4 = полный, 99 = отмененный) или короткий буквенно-цифровой код («NEW», «DRA», «INV»). "," COM "," CAN "). Последнее делает код (в программе или в базе данных) более читабельным, что, как правило, хорошо. С другой стороны, числовые коды облегчают, например, сравнение "больше чем" или "меньше чем"
источник
status.draft=Draught
Три правила реляционных баз данных:
Так что ваш вопрос отвечает сам. Сохраняйте статус внутри своей таблицы и используйте GUID / UUID в качестве идентификатора . Индексированные GUID очень быстрые и устраняют проблемы, свойственные увеличивающимся числам. С помощью идентификатора вы можете делать классные вещи, например, запрашивать в БД все завершенные записи с использованием идентификатора, а поскольку вы работаете в рамках реляционной парадигмы БД, это очень быстро. Если у вас есть только поле, БД должна циклически проходить по каждой строке и сравнивать текст, возможно, с помощью манипулирования, и это очень медленно.
Названия статусов постов могут меняться, больше информации о статусе постов можно найти в таблице, все просто работает, если вы нормализуете .
Например, вы можете добавить уровни статуса в качестве дополнительной информации, что позволит для сравнения упоминает ammoQ. Но они не зависят от ключа для позиционирования, позволяя переупорядочивать уровень статуса без ущерба для целостности БД. Вы также можете вставить дополнительные уровни, что довольно сложно, если у вас есть уровень, связанный с автоинкрементным ключом.
источник
Да, вы должны пойти с вариантом 2, имея таблицу PostStatus.
Помимо всех преимуществ, упомянутых в других ответах.
Помня о том, что статусы нужно добавлять или удалять, вы можете иметь столбец «включено» в таблице PostStatus, поэтому, если статус будет удален, пометьте столбец «включен» как «N», таким образом вы сможете добавить или удалить статусы, а также существующие записи останутся без проблем.
источник
Я хотел бы добавить к иначе проницательным ответам, что для полной нормализации изменение статуса сущности фактически моделируется в отдельной сущности, например с именем statusChange.
Вам понадобится дополнительное объединение с сущностью statusChange, но вы получите возможность добавления дополнительной информации, такой как актер, выполняющий изменение, возможные комментарии о том, почему произошло изменение, и дату, когда выполняется statusChange, и, возможно, даже когда это становится эффективным.
источник
Использование текста для статуса в таблице записей, вероятно, не будет хорошей идеей, поскольку это может измениться, и будет трудно выполнить какие-либо проверки целостности данных при вставке / обновлении. Если вы используете СУБД с типом данных enum, вы можете использовать это вместо этого (производительность, вероятно, не пострадает ... в зависимости).
Если вашему статусу нужны какие-либо метаданные (описание, созданное, понятное имя, ...), вам нужно будет хранить статусы в отдельной таблице и иметь ключ статуса в своей таблице записей (убедитесь, что вы используете внешний ключ). Идентификатор не обязательно должен быть числом, просто PK таблицы состояния. Кроме того, если статусы находятся в их собственной таблице, вы можете поделиться ими между типами записей (таблицами), если это применимо. Я не буду беспокоиться о проблемах производительности при присоединении к таблице состояния.
Что бы вы ни делали, убедитесь, что вы избегаете магических статусов (1 для активного, 2 для удаленного, ...). Это опирается на документацию и традиции, которые всегда имеют тенденцию затеряться на достаточно большом сроке. Если вы вообще используете числовые идентификаторы, убедитесь, что в вашей базе данных есть текстовая ассоциация.
источник
Зависит от цели проектирования базы данных.
Если вы проектируете базу данных просто для поддержки приложения (то есть объекты (код) являются главными для всех), то использование перечисления (или перечисления psuedo для классов, которые их не поддерживают) и сохранение имени перечисления является хорошая идея, потому что вы по-прежнему управляете значениями, разрешенными через перечисление, и вы также немного облегчаете чтение таблицы, когда вынуждены просматривать необработанные данные (что не так часто, если код фактически управляет всеми). Но если перечисление помечено. Затем я обычно сохраняю значение enum (целое число).
источник
Статус очень важен, каждый раз, когда вы получаете информацию о сообщении, вам нужно получить его статус, или вы захотите фильтровать сообщения по статусу. Если у вас есть статус в другой таблице, вам нужно будет объединиться, чтобы получить эту информацию, и поэтому производительность снижается. Определенно вы должны иметь статус в той же таблице. И поместите индекс на это! Вы все еще можете использовать целые числа в качестве статуса или, может быть, поле enum.
источник
Правильное решение - использовать хранилище событий / источник с CQRS или блокчейн. Проблема с захватом событий в RDB заключается в том, что RDB хранит моментальный снимок одного события во времени, а такие вещи, как «Состояния / Состояния», представляют собой последовательность мутаций, которые развиваются с течением времени.
источник