una tabla ser puede llaves llave foreign foraneas foranea creada como clave agregar php mysql constraints

tabla - ¿Qué tan importantes son las restricciones como NOT NULL y FOREIGN KEY si siempre controlaré la entrada de mi base de datos con PHP?



llaves foraneas mysql workbench (15)

Intento crear una columna en una tabla que sea una clave externa, pero en MySQL eso es más difícil de lo que debería ser. Me requeriría volver y realizar ciertos cambios en una tabla que ya está en uso. Entonces me pregunto, ¿qué tan necesario es para MySQL estar seguro de que cierto valor es apropiado? ¿No podría simplemente hacer eso con un lenguaje como PHP, que estoy usando para acceder a esta base de datos de todos modos ?

Del mismo modo con NOT NULL. Si solo tengo acceso a esta base de datos con PHP, ¿no podría simplemente asegurarme de que PHP no ingrese ningún valor nulo?

¿Por qué debería usar MySQL para hacer cumplir estas restricciones, cuando podría hacerlo con PHP?

Me doy cuenta de que NOT NULL es una parte muy estúpida para descuidar por las razones anteriores. Pero MySQL no aplica llaves extranjeras sin un serio grado de monkeying.

En su opinión, ¿seguiría siendo malo utilizar las claves externas "falsas", y simplemente verificar si los valores que se ingresan se corresponden en otras tablas, con PHP?


  1. No creo que pueda estar seguro de que su base de datos solo será visitada por PHP y, si es así, por parte de los desarrolladores que la usarán para respetar esas restricciones durante todo el ciclo de vida de su base de datos.

  2. Si incluye estas restricciones en su esquema, entonces puede obtener una buena idea de cómo se usan y relacionan los datos mediante la investigación de su esquema. Si solo pone todo eso en el código, entonces alguien debería buscar tanto en la base de datos como en el código PHP.

Pero, ¿no debería estar eso en la documentación de diseño, el diccionario de datos y el diseño de la base de datos lógica?

Sí, pero estos documentos son notorios por estar desactualizados y obsoletos. Sé que nunca permitiría que eso sucediera, pero algunas personas que tienen experiencia en proyectos con menos disciplina pueden asumir esto sobre su proyecto, y desean consultar el código y el esquema reales en lugar de la documentación.


¡Es importante implementar restricciones en la base de datos porque es imposible predecir el futuro! Nunca se sabe cuándo cambiarán sus requisitos.

También considere la posibilidad de que tenga varios desarrolladores trabajando en la misma aplicación. Puede que sepa cuáles son todas las limitaciones, pero un desarrollador junior no. Con restricciones en la base de datos, el código del desarrollador junior generará un error, y sabrá que algo necesita ser reparado. Sin las restricciones, el código puede no fallar y los datos podrían dañarse.


Ellos son bastante importantes. No quiere definir su modelo completamente a través de PHP. ¿Qué pasa si hay un error en tu código PHP? Podría fácilmente tener columnas anuladas donde las reglas de su negocio establezcan que no debería. Al definirlo en el nivel de la base de datos, al menos puede obtener ese cheque de forma gratuita. Realmente lo odiarás cuando haya errores en tu PHP o si alguna otra herramienta alguna vez usa tu base de datos. Solo estás preguntando por un problema, en mi humilde opinión.

Tenga en cuenta, esta es la versión muy corta de la historia.


Normalmente estoy a favor de declarar restricciones en la base de datos. Argumentos para las restricciones:

  • El código declarativo es más fácil de hacer que el código Imperativo. Las restricciones se aplican incluso si el código de la aplicación contiene errores.
  • Admite el principio "No repetir", si tiene múltiples aplicaciones o módulos de código que acceden a la misma base de datos y necesita reglas de negocio que se apliquen de manera uniforme. Si necesita cambiar la restricción, puede hacerlo en un solo lugar, incluso si tiene muchas aplicaciones.
  • Aplica la integridad de los datos incluso cuando las personas intentan eludir la aplicación, utilizando herramientas de consulta ad hoc para jugar con la base de datos.
  • Aplica consistencia, lo que significa que siempre puede estar seguro de que los datos están en un estado válido antes y después de cualquier actualización de datos. Si no usa restricciones, es posible que deba ejecutar consultas periódicas para verificar referencias rotas y limpiarlas.
  • Puede modelar la actualización / eliminación en cascada fácilmente con restricciones. Hacer lo mismo en el código de la aplicación es complejo e ineficiente, no se pueden aplicar cambios atómicamente (aunque se recomienda el uso de aislamiento de transacción) y es susceptible a errores.
  • Las restricciones ayudan a las bases de datos a ser más autodocumentadas, al igual que los nombres de columna y los tipos de datos SQL ayudan.

Argumentos contra restricciones:

  • Las reglas empresariales más complejas no se pueden modelar mediante restricciones declarativas, por lo que debe implementar algunas en el espacio de aplicación de todos modos. Teniendo en cuenta eso, ¿por qué no implementar todas las reglas comerciales en un solo lugar (su aplicación) y en el mismo idioma? Esto facilita la depuración, prueba y seguimiento de revisiones de código.
  • Las restricciones a menudo implican índices, que incurren en cierta cantidad de sobrecarga durante inserciones / actualizaciones. Por otro lado, incluso si no declara una restricción, probablemente necesite un índice de todos modos, porque la columna se puede usar en los criterios de búsqueda o unir condiciones con frecuencia.
  • Las restricciones pueden complicar tus intentos de "limpiar" errores en los datos.
  • En su proyecto actual, la incompatibilidad de MyISAM frente a InnoDB con respecto a las restricciones referenciales está causando algo de dolor.

Permitir estas restricciones en MySQL toma casi cero tiempo. Si lo salvan incluso de un solo error debido a PHP u otro código defectuoso, ¿no vale la pena?

Tenga en cuenta que los tipos de errores de los que se salvará pueden ser desagradables. Encontrar y arreglar el error en sí mismo puede no ser difícil; Lo desagradable es que una vez que hayas solucionado el error, te quedarán muchos datos defectuosos que ni siquiera pueden salvarse.

Ni siquiera abordaría este problema desde el ángulo "bueno, algo que no sea que PHP pueda acceder a tus datos algún día". Eso es cierto, pero aún más importante en mi mente son los dolores de cabeza, el tiempo (dinero) y la pérdida de datos que puede ahorrarse simplemente agregando algunas restricciones simples.


Si puede jurar por su vida que nada va a acceder a la base de datos de ninguna otra manera, entonces su página de PHP (por supuesto, libre de errores), entonces hacerlo solo con PHP estará bien.

Dado que los escenarios del mundo real siempre contienen cierta incertidumbre, es bueno que el servidor de BD vigile la integridad de sus datos.

Para las bases de datos simples, las restricciones de integridad referencial pueden no ser un requisito absoluto, sino que son agradables de tener. Cuanto más compleja es la aplicación, más beneficios puede sacar de ella. Planificarlos temprano te facilita la vida más adelante.

Además, la integridad referencial es parte de forzar el diseño de la base de datos de una manera más acorde con el libro, porque no todos los ataques sucios son posibles. Esto también es algo bueno.


Use la base de datos para integridad de datos estructurales, y use la capa BR para el resto. Y detectar errores tan pronto como sea posible. Trabajan juntos.

Con suerte, cuando su código haya madurado, no experimentará errores de RBI de Databse; y puedes anunciarte orgullosamente ser el primero.


Vas a cometer errores con PHP, 100% garantizado. PHP es de procedimiento Lo que quieres son restricciones declarativas. Desea contar toda la pila: "Estas son las limitaciones de los datos, y estas restricciones no se pueden violar". No desea mucho con el "Paso 1 ... Paso 2 ... Paso 3 ... Paso 432 ...", como su método para imponer restricciones a los datos, porque

  • lo vas a equivocar
  • cuando lo cambies más tarde, te olvidarás de lo que hiciste ahora
  • nadie más sabrá todas estas limitaciones implícitas como las conoce ahora, y eso incluye su yo futuro
  • Se necesita mucho código para hacer cumplir las restricciones de manera adecuada y todo el tiempo: el servidor de la base de datos ya tiene este código, pero ¿estás preparado para escribirlo?

La pregunta debería estar redactada de la siguiente manera: "¿Por qué debería usar PHP para hacer cumplir estas restricciones, cuando podría hacerlo con MySQL?"


Incluso si su código PHP está perfectamente libre de errores, puede detener el script intermedio (error de memoria, segfault en alguna biblioteca, etc.), dejando cosas insertadas a medias en la base de datos, de ahí la importancia de usar InnoDB y transacciones.

Lo mismo para las restricciones, por supuesto, debe tener la validación de forma adecuada y las limitaciones de la base de datos para detectar errores.

Las restricciones de la base de datos son fáciles de especificar, encontrar errores en la aplicación es difícil e incluso más difícil sin restricciones.

Mi experiencia ha sido que las bases de datos con restricciones inadecuadas, y cualquier cosa que use MyISAM, TENDRÁN datos incoherentes después de unos meses de uso, y es muy difícil encontrar de dónde vino.


Hacer que su nivel de datos haga cumplir la coherencia de los datos a través de restricciones ayuda a garantizar que sus datos se mantengan consistentes y proporciona una comprobación de fallas de tiempo de ejecución económica dentro de su aplicación.

Si cree que las limitaciones no valen la pena, tiene un sistema pequeño / que no es crítico para la misión o está dejando pasar una gran oportunidad para mejorar la calidad de su sistema. Esto no puede ser subestimado.

Las opciones incluyen: elegir un RDBMS diferente, reinventar su propio sistema de metadatos o gestionar restricciones manualmente. La administración manual en consultas sin un sistema de metadatos se vuelve rápidamente inviable para mantener y auditar adecuadamente a medida que crece la complejidad del esquema / sistema y complica innecesariamente un esquema en evolución.

Mi recomendación es elegir un RDBMS diferente.

La verificación de coherencia es mucho más difícil de lo que piensas. Por ejemplo, MySQL usa la coherencia de lectura transaccional, lo que significa que los valores que está comprobando pueden no ser los mismos valores en el alcance de otra transacción. La estrategia de coherencia para el acceso simultáneo es muy difícil de obtener si no está directamente vinculada al nivel de datos.

Cuando todo está dicho y hecho, incluso con una modesta cantidad de esfuerzo puesto en verificación manual, el resultado probable es que uno todavía podría conducir un camión a través de los casos de esquina que no ha tenido en cuenta o cometió un error al formarse.

En su pregunta NOT NULL ... Los requisitos obvios del campo de datos son un buen punto de partida. Aquí hay un par de otras cosas a considerar cuando se define la anulabilidad de la columna.

Proporciona una garantía que puede ser muy útil al escribir consultas. Varias combinaciones pueden usar condiciones NULL para mostrar una coincidencia de una fila de tabla separada de un valor NULL que no se puede suponer si la condición permite valores nulos. (Si se permiten valores NULL, una coincidencia puede significar que la fila no coincide o la fila sí coincide, pero el valor de la columna es nulo).

El uso de NOT NULL también ayuda a definir las reglas para consultas más simples que coinciden con los valores. Como no se puede decir "CUANDO valor1 = valor2" si tanto valor1 como valor2 son NULL, el resultado de la evaluación sigue siendo falso.


Agradezco mucho su pregunta, ya que estoy profundamente convencido de que las reglas de valores predeterminados deben implementarse en el lado del código, no en el de la base de datos, y esto por una razón muy simple: cuando los usuarios inician cambios en la base de datos ( INSERTOS, SELECCIONES y ACTUALIZACIONES), estos cambios integrarán todas las reglas comerciales, y los valores predeterminados son básicamente reglas comerciales:

  • No hay factura sin número de factura
  • No hay línea de factura sin cantidad, y 0 o nulos no son aceptables
  • No hay correo entrante sin fecha de recepción
  • etc

Hace algunos años decidimos deshacernos de todos estos artefactos del "lado de la base de datos", como "no nulo", "(no) permitir cadenas vacías" y otros trucos de "valor predeterminado", y funciona perfectamente. Los argumentos a favor del valor predeterminado se refieren principalmente a un tipo de principio de "seguridad" ("hazlo en el lado de la base de datos porque lo olvidarás en el lado del código / tu idioma no está hecho para eso / es más fácil hacerlo) en el lado de la base de datos ") que no tiene ningún sentido una vez que haya elegido no implementar ningún valor predeterminado en el lado de la base de datos: simplemente verifique que las reglas de su empresa estén implementadas correctamente durante la depuración.

Durante los últimos 2 años, nadie en el equipo pensó en declarar un valor predeterminado en una tabla. Supongo que nuestro aprendiz más joven ni siquiera sabe algo que se llama "valor predeterminado".

EDITAR: releyando algunas de las respuestas aquí, mi comentario final sería: hazlo en cualquier lado, ya sea DB o código, ¡pero haz tu elección y hazlo de un lado solamente! No hay nada más peligroso que tener tales controles en ambos lados, porque eventualmente (1) nunca sabrás si ambos lados están realmente implementando la misma regla, lo que significa que (2) verificar las reglas significará verificar ambos lados, lo que realmente puede convertirse en un desastre! La peor situación es, por supuesto, cuando una parte del trabajo se realiza en el lado de la base de datos (es decir, las reglas que se identificaron cuando se creó la base de datos) y la otra parte (es decir, las reglas recién identificadas) en el lado del cliente ... pesadilla ....


Implementar valores y restricciones predeterminados en el nivel de la base de datos; reglas que darán como resultado datos aceptables para cualquier aplicación consumidora. Esto lo aísla de problemas de integridad.

Luego, implemente mejores valores predeterminados y restricciones en el nivel de la aplicación. Si tiene prohibido técnicamente ( acceso a APIs externas a la base de datos ) implementar una restricción o generar un valor predeterminado a nivel de base de datos, la aplicación es donde tendrá que hacerlo. Esto dará como resultado un mejor valor predeterminado. Sin embargo, una falla de segmentación o falla general de la aplicación no dará como resultado la persistencia de datos inaceptables.


Lo más importante acerca de usar NOT NULL para mí es más la parte de documentación. Cuando vuelvo al proyecto después de unos meses, olvido en qué columnas es aceptable tener nulos. Si la columna dice NOT NULL, entonces sé que nunca tendré que lidiar con posibles valores nulos. Y si permite nulo, entonces sé con certeza que tengo que lidiar con ellos.

La otra cosa es que, como otros han notado: es posible que te pierdas algo en alguna parte, y limpiar datos es una mierda, o puede ser completamente imposible. Es mejor saber con certeza que todos los datos en su base de datos son consistentes.


No puede "simplemente" hacerlo con PHP por la misma razón que los programadores "simplemente" no pueden escribir código libre de errores. Es más difícil de lo que piensas Especialmente si crees que no es tan difícil.


Me temo que este es un tema religioso.

Desde un punto de vista purista, desea que la base de datos tenga la integridad referencial. Esto es ideal cuando tiene una multiplicidad de aplicaciones que acceden a la base de datos, porque las restricciones están en un solo lugar. Desafortunadamente, el mundo real no es ideal.

Si tiene que aplicar algún tipo de integridad referencial, en mi experiencia, su aplicación deberá saber cómo hacerlo. Esto es independientemente de si es el árbitro final, o la base de datos también lo verifica. E incluso si la base de datos tiene la integridad referencial, entonces la aplicación debe saber qué hacer si la base de datos rechaza una actualización, porque se violaría la integridad referencial ...

Como nota al margen, la configuración de MySQL para admitir restricciones de clave externa es un poco un proceso porque necesita pasar a InnoDB . Si lo hace, puede obtener un gran rendimiento estableciendo innodb_flush_log_at_tx_commit en 1. Pero probablemente sería mejor si en su lugar puede rediseñar su sitio para que sea compatible con las transacciones. Entonces obtienes dos beneficios de InnoDB.