Представьте себе веб-форму с набором флажков (можно выбрать любой или все из них). Я решил сохранить их в списке значений, разделенных запятыми, которые хранятся в одном столбце таблицы базы данных.
Теперь я знаю, что правильным решением будет создание второй таблицы и правильная нормализация базы данных. Простое решение было реализовано быстрее, и я хотел быстро проверить концепцию этого приложения и не тратить на него слишком много времени.
Я думал, что сэкономленное время и более простой код того стоили в моей ситуации, это оправданный выбор дизайна или я должен был его нормализовать с самого начала?
Еще немного контекста, это небольшое внутреннее приложение, которое по сути заменяет файл Excel, который хранился в общей папке. Я также спрашиваю, потому что я думаю о том, чтобы очистить программу и сделать ее более понятной. Там есть некоторые вещи, которыми я не совсем доволен, одна из них - тема этого вопроса.
источник
Ответы:
В дополнение к нарушению формы First Normal из-за повторяющейся группы значений, хранящихся в одном столбце, у разделенных запятыми списков есть много других более практических проблем:
idlist REGEXP '[[:<:]]2[[:>:]]'
*Чтобы решить эти проблемы, вы должны написать тонны кода приложения, заново изобретая функциональность, которую СУБД уже обеспечивает гораздо более эффективно .
Разделенные запятыми списки настолько ошибочны, что я сделал это первой главой своей книги: « Антипаттерны SQL: предотвращение ловушек программирования баз данных» .
Есть моменты, когда вам нужно использовать денормализацию, но, как упоминает @OMG Ponies , это исключительные случаи. Любая нереляционная «оптимизация» приносит пользу одному типу запроса за счет других видов использования данных, поэтому убедитесь, что вы знаете, какие из ваших запросов необходимо обрабатывать настолько специально, чтобы они заслуживали денормализации.
* MySQL 8.0 больше не поддерживает этот синтаксис выражения границы слова.
источник
«Одной из причин была лень».
Это звонит в тревогу. Единственная причина, по которой вы должны делать что-то подобное, состоит в том, что вы знаете, как сделать это «правильным образом», но вы пришли к выводу, что есть реальная причина не делать это таким образом.
Сказав это: если данные, которые вы выбираете для хранения таким способом, представляют собой данные, к которым вам никогда не потребуется запрашивать данные, то, возможно, есть смысл хранить их так, как вы выбрали.
(Некоторые пользователи оспаривают утверждение в моем предыдущем абзаце, говоря, что «вы никогда не знаете, какие требования будут добавлены в будущем». Эти пользователи либо вводят в заблуждение, либо высказывают религиозные убеждения. Иногда выгодно работать с требованиями, которые вы иметь перед вами.)
источник
Есть много вопросов о том, как задать вопрос:
Другая проблема со списком, разделенным запятыми, заключается в обеспечении согласованности значений - хранение текста означает возможность опечаток ...
Все это симптомы денормализованных данных и подчеркивают, почему вы всегда должны моделировать для нормализованных данных. Денормализация может быть оптимизацией запроса, которая должна применяться, когда потребность действительно возникает .
источник
В общем, все может быть оправдано, если оно отвечает требованиям вашего проекта. Это не значит, что люди согласятся или захотят защитить ваше решение ...
Как правило, хранение данных таким образом неоптимально (например, сложнее выполнять эффективные запросы) и может вызвать проблемы с обслуживанием, если вы измените элементы в своей форме. Возможно, вы могли бы найти золотую середину и использовать вместо этого целое число, представляющее набор битовых флагов?
источник
Да, я бы сказал, что это действительно так плохо. Это оправданный выбор, но это не делает его правильным или хорошим.
Это ломает первую нормальную форму.
Вторая критика заключается в том, что помещение необработанных входных результатов непосредственно в базу данных без какой-либо проверки или связывания вообще делает вас открытыми для атак с использованием SQL-инъекций.
То, что вы называете ленью и отсутствием знаний по SQL, - это то, из чего сделаны новички. Я бы порекомендовал потратить время на то, чтобы сделать это правильно и расценить это как возможность учиться.
Или оставьте все как есть и изучите болезненный урок атаки SQL-инъекцией.
источник
Я использую разделенный табуляцией список ключ / значение в столбце NTEXT в SQL Server уже более 4 лет, и он работает. Вы теряете гибкость при создании запросов, но, с другой стороны, если у вас есть библиотека, которая сохраняет / удерживает пару ключей / значений, тогда это не такая уж плохая идея.
источник
Мне нужен столбец с несколькими значениями, он может быть реализован как поле XML
Он может быть преобразован в запятую при необходимости
запрос списка XML на сервере sql с использованием Xquery .
Будучи полем xml, можно решить некоторые проблемы.
С CSV: Не могу гарантировать, что каждое значение является правильным типом данных: нет способа предотвратить 1,2,3, банан, 5
С XML: значения в теге могут быть принудительного типа
С CSV: нельзя использовать ограничения внешнего ключа, чтобы связать значения с таблицей поиска; нет способа обеспечить ссылочную целостность.
С XML: все еще проблема
С CSV: не может обеспечить уникальность: нет способа предотвратить 1,2,3,3,3,5
С XML: все еще проблема
С CSV: невозможно удалить значение из списка без извлечения всего списка.
С XML: отдельные элементы могут быть удалены
С CSV: трудно найти все объекты с данным значением в списке; Вы должны использовать неэффективное сканирование таблицы.
С XML: поле XML может быть проиндексировано
С CSV: трудно подсчитать элементы в списке или выполнить другие агрегированные запросы. **
С XML: не особенно сложно
С CSV: сложно объединить значения в справочную таблицу, на которую они ссылаются. **
С XML: не особенно сложно
С CSV: трудно получить список в отсортированном порядке.
С XML: не особенно сложно
С CSV: Хранение целых чисел в виде строк занимает примерно вдвое больше места, чем хранение двоичных чисел.
С XML: хранилище еще хуже, чем CSV
С CSV: плюс много запятых.
С XML: теги используются вместо запятых
Короче говоря, использование XML позволяет обойти некоторые проблемы со списком с разделителями и при необходимости может быть преобразовано в список с разделителями.
источник
Да, это так плохо. Я считаю, что если вам не нравится использование реляционных баз данных, тогда ищите альтернативу, которая подходит вам лучше, есть много интересных проектов "NOSQL" с некоторыми действительно продвинутыми функциями.
источник
Я бы, вероятно, занял среднюю позицию: превратить каждое поле в CSV в отдельный столбец в базе данных, но не сильно беспокоиться о нормализации (по крайней мере, пока). В какой-то момент нормализация может стать интересной, но со всеми данными, помещенными в один столбец, вы практически не получаете никакой выгоды от использования базы данных вообще. Вам нужно разделить данные на логические поля / столбцы / как угодно, чтобы вызывать их, прежде чем вы сможете вообще с ними манипулировать.
источник
Если у вас есть фиксированное число логических полей, вы можете использовать
INT(1) NOT NULL
(или,BIT NOT NULL
если оно существует) илиCHAR (0)
(обнуляемое) для каждого. Вы также можете использоватьSET
(я забыл точный синтаксис).источник
INT(1)
занимает 4 байта;(1)
не имеет смысла.