Насколько важны ограничения, такие как NOT NULL и FOREIGN KEY, если я всегда буду контролировать вход в базу данных с помощью PHP?

Я пытаюсь создать столбец в таблице, которая является внешним ключом, но в MySQL это сложнее, чем должно быть. Это потребует от меня возврата и внесения определенных изменений в уже используемую таблицу. Поэтому я задаюсь вопросом, насколько необходимо MySQL для уверенности в том, что определенное значение подходит? Не могу ли я просто сделать это с помощью языка, такого как PHP, который я использую для доступа к этой базе данных?

Аналогично NOT NULL. Если я получаю доступ только к этой базе данных с помощью PHP, не могу ли я просто заставить PHP гарантировать, что значение null не будет введено?

Почему я должен использовать MySQL для обеспечения соблюдения этих ограничений, когда я мог бы просто сделать это с помощью PHP?


Я понимаю, что NOT NULL – очень глупая часть, чтобы пренебречь вышеупомянутыми причинами. Но MySQL не применяет внешние ключи без серьезной обезьяны.

На ваш взгляд, было бы плохо использовать «поддельные» внешние ключи и просто проверить, соответствуют ли значения, которые будут введены в других таблицах, с помощью PHP?

    Вы будете делать ошибки с PHP, гарантированно 100%. PHP является процедурным. То, что вы хотите, – это декларативные ограничения. Вы хотите рассказать весь стек: «Это ограничения на данные, и эти ограничения не могут быть нарушены». Вы не хотите много обсуждать «Шаг 1 … Шаг 2 … Шаг 3 … Шаг 432 …», как ваш метод принудительного ограничения данных, потому что

    • вы ошибетесь
    • когда вы измените его позже, вы забудете, что вы сделали сейчас
    • никто другой не узнает все эти неявные ограничения, как вы их знаете сейчас, и это включает в себя ваше будущее
    • требуется много кода для правильного использования ограничений и все время – сервер базы данных уже имеет этот код, но готовы ли вы его написать?

    На самом деле вопрос должен быть сформулирован следующим образом: «Почему я должен использовать PHP для принудительного применения этих ограничений, когда я мог бы просто сделать это с помощью MySQL?»

    Вы не можете «просто» сделать это с PHP по той же причине, что программисты «просто» не могут писать код без ошибок. Это сложнее, чем вы думаете. Особенно, если вы думаете, что это не так сложно.

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

    Поскольку в реальных сценариях всегда присутствует некоторая неопределенность, хорошо иметь сервер БД, следящий за целостностью ваших данных.

    Для простых баз данных ограничения ссылочной целостности могут быть не абсолютным требованием, а приятным. Чем сложнее приложение, тем больше пользы вы можете извлечь из них. Планирование их в раннем возрасте облегчит вам жизнь.

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

    Они очень важны. Вы не хотите полностью определять свою модель через PHP. Что делать, если в вашем PHP-коде есть ошибка? Вы можете легко иметь нулевые столбцы, в которых ваши бизнес-правила утверждают, что вы не должны. Определив его на уровне базы данных, вы, по крайней мере, получите эту проверку бесплатно. Вы действительно будете ненавидеть, когда на вашем PHP есть ошибки, или если какой-либо другой инструмент когда-либо использует вашу базу данных. Вы просто просите проблему, ИМХО.

    Будьте внимательны, это очень короткая версия истории.

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

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

    Обычно я выступаю за объявление ограничений в базе данных. Аргументы для ограничений:

    • Декларативный код проще сделать без ошибок, чем императивный код. Ограничения выполняются, даже если код приложения содержит ошибки.
    • Поддерживает принцип «Не повторяйте себя», если у вас есть несколько приложений или модулей кода, обращающихся к одной и той же базе данных, и вам необходимо, чтобы правила бизнеса были соблюдены единообразно. Если вам нужно изменить ограничение, вы можете сделать это в одном месте, даже если у вас много приложений.
    • Обеспечивает целостность данных, даже когда люди пытаются обойти приложение, используя специальные инструменты запроса, чтобы возиться с базой данных.
    • Обеспечивает согласованность, что означает, что вы всегда можете быть уверены, что данные находятся в допустимом состоянии до и после любого обновления данных. Если вы не используете ограничения, вам может потребоваться выполнить периодические запросы, чтобы проверить наличие неработающих ссылок и очистить их.
    • Вы можете легко моделировать каскадное обновление / удаление с помощью ограничений. То же самое в коде приложения является сложным и неэффективным, не может применяться изменения атомарно (хотя рекомендуется использовать изоляцию транзакций) и подвержен ошибкам.
    • Ограничения помогают базам данных быть более самодокументируемыми, так же как и имена столбцов и типы данных SQL.

    Аргументы против ограничений:

    • Более сложные бизнес-правила не могут быть смоделированы с помощью декларативных ограничений, поэтому вы должны каким-либо образом реализовать их в прикладном пространстве. Учитывая это, почему бы не реализовать все бизнес-правила в одном месте (ваше приложение) и на одном языке? Это упрощает отладку, проверку и отслеживание изменений кода.
    • Ограничения часто включают в себя индексы, которые несут некоторые накладные расходы во время вставок / обновлений. С другой стороны, даже если вы не объявляете ограничение, вам, вероятно, понадобится индекс, потому что столбец часто может использоваться в критериях поиска или в условиях объединения.
    • Ограничения могут усложнить ваши попытки «очистить» ошибки в данных.
    • В вашем текущем проекте несовместимость MyISAM и InnoDB в отношении ссылочных ограничений вызывает некоторое горе.

    Включение этих ограничений в MySQL занимает почти нулевое время. Если они избавят вас от одной ошибки из-за неправильного PHP или другого кода, разве это не стоит того?

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

    Я бы даже не стал подходить к этой проблеме из «хорошо, что-то другое, кроме PHP, которое могло бы получить доступ к вашим данным когда-нибудь». Это правда, но еще важнее в голове – головные боли, время (деньги) и потеря данных, которые вы можете сэкономить, просто добавив несколько простых ограничений.

    Используйте базу данных для целостности структурных данных и используйте уровень BR для остальных. И уловить ошибки как можно раньше. Они работают вместе.

    Если повезет, когда ваш код будет созрел, вы не столкнетесь с ошибками RI Databse; и вы можете с гордостью объявить себя первым.

    Даже если ваш PHP-код абсолютно не содержит ошибок, он может остановить средний скрипт (из-за ошибки памяти, segfault в какой-то библиотеке и т. Д.), Оставив в базе данных половину вставленного материала, следовательно, важность использования InnoDB и транзакций.

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

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

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

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

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

    Выбор включает в себя: выбор другой СУБД, повторное использование собственной системы метаданных или ручное управление ограничениями. Ручное управление в запросах без системы метаданных быстро становится неосуществимым для надлежащего поддержания и проверки, поскольку сложность схемы / системы возрастает и необоснованно усложняет эволюционирующую схему.

    Моя рекомендация – выбрать другую СУБД.

    Проверка согласованности намного сложнее, чем вы думаете. Например, MySQL использует транзакционную согласованность чтения, что означает, что значения, которые вы проверяете, могут не совпадать с значениями в другой транзакции. Согласованные scemantics для одновременного доступа очень трудно получить право, если они не связаны непосредственно с уровнем данных.

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

    На ваш NOT NULL вопрос … Очевидные требования к полям данных являются хорошей отправной точкой. Вот несколько других вещей, которые следует учитывать при определении значения столбца.

    Он обеспечивает гарантию, которая может быть очень полезна при написании запросов. Различные объединения могут использовать условия NULL, чтобы показать несоответствие строки таблицы, отдельно от значения NULL, которое невозможно принять, если условие допускает null. (Если допустимы NULL, совпадение может означать либо совпадение строки, либо совпадение строки, но значение столбца равно нулю).

    Использование NOT NULL также помогает определять правила для более простых запросов, соответствующих значениям. Поскольку вы не можете сказать «WHEN value1 = value2», если значения value1 и value2 равны NULL, результат оценки остается ложным.

    Самое важное в использовании NOT NULL для меня – это больше часть документации. Когда я вернусь в проект через несколько месяцев, я забуду, в каких столбцах допустимо иметь нули. Если в столбце указано NOT NULL, то я знаю, что мне никогда не придется иметь дело с потенциальными нулевыми значениями из него. И если он разрешает null, то я точно знаю, что с ними нужно иметь дело.

    Другое дело, как отмечали другие: вы можете что-то пропустить, а очистка данных отстой или может быть совершенно невозможной. Лучше знать, что все данные в вашей базе данных согласованы.

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

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

    Но разве это не должно быть в конструкторской документации, словарях данных и дизайне логической базы данных?

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

    Я высоко ценю ваш вопрос, так как я глубоко убежден, что правила по умолчанию должны быть реализованы на стороне кода, а не на стороне базы данных, и это по очень простой причине: когда пользователи инициируют изменения базы данных ( INSERTS, SELECTS и UPDATES), эти изменения должны включать все бизнес-правила, а значения по умолчанию – это в основном бизнес-правила:

    • Нет счета-фактуры без номера счета-фактуры
    • Нет строки счета без количества, и 0 или нули не приемлемы
    • Нет входящей почты без даты приема
    • и т.д

    Мы решили несколько лет назад избавиться от всех этих артефактов на стороне базы данных, таких как «не null», «(не разрешать пустые строки» и т. Д.), И это отлично работает. Аргументы в пользу значения по умолчанию в основном относятся к своего рода принципу «безопасности» («делать это на стороне базы данных, потому что вы забудете это на стороне кода / ваш язык не создан для этого / это проще сделать на стороне базы данных "), что не имеет никакого смысла, если вы решили не применять какое-либо значение по умолчанию на стороне базы данных: просто убедитесь, что ваши бизнес-правила правильно реализованы во время отладки.

    В течение последних 2 лет никто в команде никогда не думал объявить значение по умолчанию в таблице. Думаю, наш младший стажер даже не знает о чем-то, что называется «значением по умолчанию».

    EDIT: перечитав некоторые из ответов здесь, мой последний комментарий был бы: сделайте это на любой стороне, будь то БД или код, но сделайте свой выбор и сделайте это только с одной стороны! Нет ничего более опасного, чем наличие такого контроля с обеих сторон, потому что в конечном итоге (1) вы никогда не узнаете, действительно ли обе стороны реализуют одно и то же правило, что означает, что (2) проверка правил будет означать проверку обеих сторон, что может реально стать беспорядком! Худшая ситуация, конечно, когда одна часть работы выполняется на стороне базы данных (то есть правила, которые были определены при создании базы данных), а другая часть (то есть новые идентифицированные правила) выполняется на стороне клиента … кошмар ….

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

    Затем реализуйте лучшие значения и ограничения по умолчанию на уровне приложения. Если вам запрещено технически ( доступ к внешним API-интерфейсам API ) от реализации ограничения или генерирование значения по умолчанию на уровне базы данных, приложение должно быть вам нужно. Это приведет к лучшему значению по умолчанию. Однако segfault или общий сбой приложения не приведут к недопустимым данным, которые сохраняются.

    Боюсь, это религиозная тема.

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

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

    В качестве связующего, настройка MySQL для поддержки ограничений внешнего ключа – это немного процесс, потому что вам нужно перейти на InnoDB . Если вы это сделаете, вы можете получить большую производительность, установив innodb_flush_log_at_tx_commit на 1. Но, вероятно, было бы лучше, если бы вы могли вместо этого перестроить свой сайт для innodb_flush_log_at_tx_commit транзакций. Затем вы получаете два преимущества InnoDB.