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

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

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

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


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

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

Попытки компенсировать это в PHP приводят к безумию. MySQL очень и очень терпимо относится к изменениям DDL с произвольным потоком.

dkretz 20.12.2008 01:45
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
22
1
6 277
15
Перейти к ответу Данный вопрос помечен как решенный

Ответы 15

Ответ принят как подходящий

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

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

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

Как вы интерпретируете исключение, возникшее в значимом сообщении об ошибке (без добавления большего количества кода, чем вы изначально получили)? И вы не верите в валидацию в клиенте?

dkretz 20.12.2008 01:02

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

ninesided 20.12.2008 01:50

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

Calyth 20.12.2008 02:21

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

yfeldblum 20.12.2008 17:37

Я в некоторой степени не согласен, у вас должны быть ограничения в ОБЕИХ местах. В коде и в базе данных, но еще одна причина для наложения ограничений в БД заключается в том, что когда-нибудь у вас может быть другое приложение, которое будет работать с той же базой данных, которому вы не можете полностью доверять.

justin.m.chase 22.12.2008 09:10

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

yfeldblum 03.01.2009 15:27

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

Имейте в виду, это очень короткая версия истории.

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

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

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

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

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

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

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

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

Philippe Grondier 20.12.2008 01:45

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

recursive 20.12.2008 02:02

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

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

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

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

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

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

stalepretzel 20.12.2008 01:06

Почему это плохая идея? В любом случае, «ALTER TABLE tablename ENGINE = InnoDB» может преобразовать заполненную таблицу из MyISAM в InnoDB. Хотя на это нужно время, в зависимости от количества данных.

Bill Karwin 20.12.2008 02:11

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

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

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

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

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

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

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

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

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

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

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

К сожалению, ваш молодой стажер, к сожалению, будет не информирован о типичных рабочих процедурах, когда перейдет к другому работодателю. Здесь упоминается еще один ответ; «Что, если вы подключите к этой базе данных другое приложение?»; если вы не можете поделиться все необходимыми библиотеками, значит, вы ошиблись.

Dan Lugg 23.03.2013 17:36

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

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

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

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

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

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

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

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

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

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

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

Я рекомендую выбрать другую СУБД.

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

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

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

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

Использование NOT NULL также помогает определить правила для более простых запросов, соответствующих значениям. Поскольку вы не можете сказать «КОГДА значение1 = значение2», если и значение1, и значение2 равны NULL, результат оценки все равно будет ложным.

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

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

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

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

+1 Совершенно верно! Кроме того, когда вы в конечном итоге пишете сценарий для устранения повреждений, он может непреднамеренно нанести БОЛЬШЕ ущерба без защиты ограничений.

HDave 08.01.2014 22:08

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

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

Другие вопросы по теме