如果我总是用PHP控制我的数据库输入,那么像NOT NULL和FOREIGN KEY这样的约束条件有多重要?

24

我试图在一个表中创建一个外键列,在MySQL中这比它应该的要困难得多。这将要求我回去对已经使用的表进行某些更改。所以我想知道,MySQL确保某个值是否适当有多重要?我是否可以只使用像PHP这样的语言来访问这个数据库,从而做到这一点呢?

同样道理,如果我只用PHP访问这个数据库,我能不能简单地让PHP确保没有空值被输入呢?

为什么我要使用MySQL来执行这些约束条件,而不是用PHP来完成呢?


我意识到由于上述原因忽略NOT NULL是非常愚蠢的。但是,如果不进行严格操作,MySQL不会强制执行外键约束。

在您的意见中,使用“伪”外键,并简单地检查要输入的值是否在其他表中匹配,然后再用PHP是否仍然是不好的呢?


1
尝试在PHP中进行补偿会导致疯狂。MySQL非常容忍滑动的DDL更改。 - dkretz
15个回答

1
即使您的PHP代码完全没有错误,它也可能在脚本中途停止(内存错误、某些库中的段错误等),从而在数据库中留下了半插入的内容,因此使用InnoDB和事务非常重要。
同样对于约束条件,当然应该进行适当的表单验证,并在其后面使用数据库约束条件来捕获错误。
数据库约束条件很容易指定,但在应用程序中查找错误很难,甚至没有约束条件更难。
我的经验是,未正确约束的数据库以及使用MyISAM的任何内容,在使用几个月后都会有不一致的数据,并且很难找到它来自哪里。

+1 没错!此外,当你编写一个脚本来修复损坏时,如果没有约束的保护,它可能会无意中造成更多的损害。 - Dave

0

在数据库层面实现默认值和约束条件,这些规则将导致任何使用应用程序都能接受的数据。这将使您免受完整性问题的影响。

然后,在应用程序层面实现更好的默认值和约束条件。如果您在技术上被禁止(访问数据库外部的API)实施约束条件或在数据库层面生成默认值,则需要在应用程序中进行操作。这将导致一个更好的默认值。但是,应用程序的段错误或一般故障不会导致无法接受的数据被持久化。


0
  1. 我认为你不能确定你的数据库只会被 PHP 访问,即使是由开发人员在整个数据库生命周期内使用也可能违反这些约束。

  2. 如果您将这些约束条件包含在架构中,则可以通过调查您的架构来了解数据的使用方式和关系。如果只将所有内容放在代码中,则需要查看数据库和 PHP 代码。

但是这些东西不应该在设计文档、数据字典和逻辑数据库设计中吗?

是的,但是这些文件因更新不及时而臭名昭著。我知道 永远不会让这种事情发生,但有些有经验的人可能会假设这种情况发生在您的项目中,并希望查阅实际的代码和架构而不是文档。


0

非常感谢您的问题,我深信默认值规则应该在代码端实现,而不是在数据库端实现,这是一个非常简单的原因:当用户发起数据库更改(INSERTS、SELECTS和UPDATES)时,这些更改应该集成所有业务规则,而默认值基本上就是业务规则:

  • 没有发票号码就没有发票
  • 没有数量的发票行是不存在的,0或null也是不可接受的
  • 没有收到日期的传入邮件是不存在的
  • 等等

我们几年前决定摆脱所有这些“数据库端”工件,如“非空”,“(不)允许空字符串”和其他“默认值”技巧,它完美地运作。支持默认值的论点主要涉及一种“安全”原则(“在数据库端执行它,因为你会忘记在代码端执行它/你的语言不适合执行它/在数据库端执行它更容易”),但一旦您选择不在数据库端实现任何默认值,这种论点就没有任何意义了:只需在调试时检查您的业务规则是否正确实现即可。

在过去的两年中,团队中没有人想过在表中声明默认值。我猜我们年轻的实习生甚至不知道什么是“默认值”。
编辑:重新阅读这里的一些答案后,我的最终评论是:在任何一方面都可以做到,无论是数据库还是代码,但要做出选择并只在一侧进行!没有比在两个方面都有这样的控制更危险的事情了,因为最终(1)你永远不会知道两个方面是否真正实施了相同的规则,这意味着(2)检查规则将意味着检查两个方面,这可能真的变得一团糟!最糟糕的情况当然是工作的一部分在数据库端完成(即创建数据库时确定的规则),而另一部分(即新确定的规则)在客户端完成...噩梦....

不幸的是,当你的年轻实习生离开公司去另一家雇主时,他将对典型的操作流程感到遗憾地无知。这里有另一个答案提到:“如果你将另一个应用程序插入到这个数据库中会怎样?”,除非你能共享所有必要的库,否则你已经弄错了。 - Dan Lugg

0

我恐怕这是个宗教话题。

从纯粹的角度来看,您希望数据库执行引用完整性。当您有多个应用程序访问数据库时,这是理想的,因为约束条件在一个地方。不幸的是,现实世界并不理想。

如果您必须执行某种引用完整性,在我的经验中,您的应用程序需要知道如何执行此操作。无论它是最终裁决者还是数据库也检查它。即使数据库执行引用完整性,那么如果数据库拒绝更新,应用程序也必须知道该怎么做,因为将违反引用完整性…

顺便说一句,设置MySQL以支持外键约束有点过程,因为您需要切换到InnoDB。如果您只是这样做,通过将innodb_flush_log_at_tx_commit设置为1,您可以获得很高的性能回报。但是,如果您能够重新设计您的站点以支持事务,则可能会更好。然后您将获得InnoDB的两个好处。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接