Як зберігати статуси записів (наприклад, очікування, завершення, чернетка, скасування ...)


18

Досить багато додатків вимагають, щоб записи в їхніх таблицях мали статус, наприклад "завершено", "чернетка", "скасовано". Який найкращий спосіб зберігання цих статусів? Щоб проілюструвати, що я тут отримую, - дуже короткий) приклад.

У мене є проста програма для блогу, і кожна публікація має статус: опублікована, чернетка або очікує на розгляд.

Як я бачу це є два способи моделювати це в базі даних.

  1. У таблиці "Пост" є текстове поле, що включає текст статусу.
  2. У таблиці "Пост" є поле статусу, яке містить ідентифікатор запису в таблиці PostStatus

Приклад блогу тут - дуже простий приклад. Де перелік (якщо він підтримується) може бути достатнім. Однак я хотів би, щоб відповіді на це питання врахували, що список статусів може змінюватися в будь-який час, тому більше можна додати або видалити.

Чи може хтось пояснити переваги / недоліки кожного?

Ура!

Моє початкове рішення щодо цього полягає в тому, що краще використовувати іншу таблицю і шукати стан як його кращий для нормалізації, і мене завжди вчили, що нормалізація корисна для баз даних


1
Також дивіться dba.stackexchange.com/q/11631/630
gbn

Що ви маєте на увазі під «будь-коли»? Чи означає це як частина діяльності користувачів або як частина циклу випуску програмного забезпечення?
кевін клайн

Обидва, у яких випадках найкраще застосовується будь-який із згаданих тут підходів. Тож якщо користувачі зможуть додати нові статуси, або якщо нові будуть додані в більш пізній момент проекту
veganista

Збереження тексту в базі даних може бути хорошою денормалізацією. Я думаю, це може залежати від точних деталей, наприклад, як часто ваша організація змінює свої процеси (що призводить до можливих змін статусу)?
Джейді

Якщо користувачі можуть додати нові статуси, то цілком інша справа. Ви, ймовірно, захочете записати створеного користувача тощо зі статусом і обов'язково знадобиться інша таблиця.
Кевін Клайн

Відповіді:


14

Збереження статусу в якості індексу в іншій таблиці - зайве ускладнення. Зберігайте стан безпосередньо в таблиці з легким читанням. У коді програми використовуйте константи або тип перерахунку. Це призведе до більш простого коду програми та полегшення налагодження рівня даних.

Це не денормалізує дані, а лише змінює подання. Якщо база даних підтримує перерахування безпосередньо, то використовуйте це. В іншому випадку використовуйте обмеження для обмеження значень стовпців. У вас буде обмеження в будь-якому випадку: або пряме обмеження на значення стовпця, або обмеження іноземного ключа.

Так, можливо, вам доведеться представляти статус різним користувачам. Це проблема презентації, яку потрібно вирішити в презентаційному шарі, а не в стійкості.


1
+1, забороняючи конкретну потребу зберігати список статусів у db, це, як правило, найпростіший, найменш складний спосіб зробити це.
ГрандмайстерB

2
Це нормально, якщо ви не почнете змінювати архітектуру статусу або зберігати дати мутації
LastTribunal

10

Збереження тексту статусу IMO не є гарною ідеєю, оскільки хтось може вирішити, що "завершений" повинен бути названий "готовим", і тоді вам доведеться оновити свою базу даних, перегляньте програму, якщо хтось жорстко закодував текст тощо.

Я бачив у багатьох програмах або числовий код (1 = новий, 2 = чернетка, 3 = під час перевірки, 4 = повний, 99 = скасований), або короткий буквено-цифровий код ("НОВО", "DRA", "INV "," COM "," CAN "). Пізніше робить код (у програмі чи в базі даних) більш зрозумілим для людини, що, як правило, є хорошою справою. З іншого боку, числові коди полегшують порівняння, наприклад, "більше" або "менше"

select * from myrecords where status < Status.Complete;

Якийсь ідіот теж може хардкор.
Морон

Ще одна перевага ідентифікаторів - вам потрібно забезпечити локалізацію. Ви можете використовувати свій ідентифікатор для пошуку рядка ресурсу та відображення. З жорстко зашифрованими рядками це неможливо
armitage

3
Я не думаю, що робити статуси, використовуючи порівняння "більше, ніж" або "менше", як ви показали, є хорошою ідеєю. Це може працювати для більш простих додатків, таких як цей приклад, але це не добре для складніших додатків (хоча я впевнений, що ви знаєте про це)
veganista

1
@armitage: цілком можливо зробити пошук за допомогою рядків. Назви ресурсів - це рядки:status.draft=Draught
kevin cline

veganista: Звичайно, можуть бути складнощі з більшими / меншими порівняннями, але я бачив великі, складні системи, які це роблять і живуть.
користувач281377

4

Три правила реляційних баз даних:

  1. Нормалізувати
  2. Нормалізувати
  3. Нормалізувати

Отже, ваше запитання відповідає самому собі. Зберігайте статус у власній таблиці та використовуйте GUID / UUID, як свій ідентифікатор . Індексований GUIDS дуже швидкий і виправляє проблеми, притаманні приросту чисел. З ідентифікатором ви можете робити цікаві речі, як-от запитати БД для всіх завершених постів, використовуючи ідентифікатор, і оскільки ви працюєте в реляційній парадигмі db, це дуже швидко. Якщо у вас є просто поле, БД повинен перебирати цикл на кожному рядку і робити порівняння тексту, можливо, із зміною, і це дуже повільно.

Назви статусу публікації можуть змінюватися, більше інформації про стан публікацій може потрапити в таблицю, все просто працює, якщо ви нормалізуєтеся .

Наприклад, ви можете додати рівні статусу як додаткову інформацію, яка б дозволила порівняти згадування ammoQ. Але вони не залежать від ключа позиціонування, що дозволяє переставляти рівень статусу без шкоди для цілісності БД. Ви також можете вставити додаткові рівні, що є досить хитрощами, якщо у вас є рівень, пов’язаний з ключем для автоматичного підвищення.


Причини, про які ви вказали тут, - це саме ті причини, з якими я використовую іншу таблицю для зберігання моїх стоянок. Основна причина, чому я задав це питання, - це зрозуміти, чи інколи корисно використовувати більш просте текстове поле.
веганіста

@Liam Тільки якщо воно нормалізується до текстового поля. Тобто, якщо ваше текстове поле залежить лише від первинного ключа, а ви шукаєте речі на основі первинного ключа , разом із текстовим полем. Реляційна БД стосується відносин, у вас їх є, тому її потрібно визначити. Одне з небагатьох винятків - якщо ви обробляєте брудні дані із зовнішнього джерела, і у вас немає часу повністю моделювати їх. Уникайте цього, якщо можливо.
Спенсер Ратбун

приховує очі, оплакуючи GUID, які ніколи не повернуться
sq33G

Ви повинні були написати "три теорії реляційних баз даних". Теорія не завжди є практичною. Часто ефективніше зберігати код статусу безпосередньо в записі, з яким він пов'язаний. Якщо вам не потрібно шукати його, щоб використовувати його, видалення приєднання до іншої таблиці заощаджує багато даремно оброблених.
Suncat2000

Захищені через неправильну інформацію про типи стовпців та сканування повних таблиць.
igorrs

3

Так, вам слід скористатися варіантом 2, маючи таблицю PostStatus.

Крім усіх переваг, згаданих в інших відповідях.

Маючи на увазі, що статуси потрібно додати або видалити, ви можете мати стовпчик "увімкнено" у таблиці PostStatus, тому якщо статус видалено, позначте стовпець "увімкнено" як "N", таким чином ви зможете додавати або видаляти статуси, а також наявні записи залишатимуться без проблем.


1

Я хотів би додати інакше проникливі відповіді, що для повної нормалізації зміна статусу суб'єкта господарювання насправді моделюється в окремому об'єкті, наприклад, з назвою "statusChange".

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


0

Використання тексту для отримання статусу в таблиці записів, ймовірно, не буде гарною ідеєю, оскільки це може змінитися, і було б важко виконати будь-які перевірки цілісності даних щодо вставки / оновлення. Якщо ви використовуєте СУБД з типом даних enum, ви можете використовувати це замість цього (продуктивність, ймовірно, не буде порушена ... залежно).

Якщо вашому статусу потрібні будь-які метадані (опис, створений дружнім іменем, ...), вам потрібно буде зберігати статуси в окремій таблиці та мати ключ статусу у вашій таблиці записів (обов’язково використовуйте іноземний ключ). Ідентифікатор не обов'язково повинен бути числом, лише PK таблиці статусу. Крім того, якщо статуси знаходяться у власній таблиці, ви можете поділитись ними на типи записів (таблиць), якщо це застосовується. Я б не переймався питаннями щодо продуктивності з приєднанням до таблиці статусу.

Що б ви не робили, не забудьте уникнути магічних статусів (1 для активних, 2 для видалених, ...). Це спирається на документацію та традиції, які завжди мають тенденцію загубитися на досить великій часовій шкалі. Якщо ви взагалі використовуєте числові ідентифікатори, переконайтеся, що де-небудь у вашому db є текстова асоціація.


Якщо ви не турбуєтесь про продуктивність, ви, ймовірно, жертвуєте масштабністю. Комп'ютери не можуть уникнути магічних статусів: 0 і 1 є суттєво магічними.
Suncat2000

0

Залежить від мети проектування бази даних.

Якщо ви базуєте базу даних просто для підтримки програми (тобто об'єкти (код) є головним), використовуючи перерахування (або перерахування psuedo для класів, які не підтримують їх), а зберігання імені перерахунку - це хороша ідея, оскільки ви все ще керуєте значеннями, дозволеними через enum, і ви також полегшуєте читати таблицю, коли ви змушені переглядати необроблені дані (що не так часто, якщо код насправді править усіма). Але якщо перерахування позначено. Тоді я зазвичай зберігаю значення enum (ціле число).


-1

Статус дуже важливий, щоразу, коли ви отримуєте інформацію про публікацію, вам потрібно буде отримати її статус, або ви хочете фільтрувати публікації за статусом. Якщо у вас є статус в іншій таблиці, вам потрібно буде приєднатися, щоб отримати цю інформацію, і таким чином продуктивність буде порушена. Однозначно ви повинні мати статус в одній таблиці. І поставте на нього індекс! Ви все ще можете використовувати цілі числа як статус або, можливо, поле перерахування.


-2

Правильне рішення - використовувати або магазин / джерело події з CQRS, або блокчейн. Проблема з захопленням подій в RDB полягає в тому, що RDB зберігає в часі знімок однієї події, а такі речі, як "Статуси / штати", - це послідовність мутацій, що розвиваються з часом


Якщо ви збираєтесь голосувати за мою посаду, тоді зробіть справу. Інакше ви просто
нерозумний
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.