PHP/MySQL - 在数据库中存储数组

3
我正在开发一款PHP应用程序,需要将各种设置存储在数据库中。客户经常要求添加或更改/移除某些内容,这已经导致了表格设计方面的问题。基本上,我有很多布尔字段,仅指示特定记录是否启用了各种设置。
为了避免进一步操作表格,我考虑将数据存储为序列化数组。我已经阅读到这被认为是不好的做法,但我认为这是使用这种方法的合理案例。
是否有任何真正的理由避免这样做?
欢迎提供建议。
谢谢。

听起来你的数据需要进行一些规范化。你能发布表结构吗? - Chris Gutierrez
5个回答

10
真正的原因是规范化,这样做将会破坏第一范式

然而,在许多情况下,违反正常形式可能被认为是合理的。你处理多少个字段并且它们全部是布尔值吗?

在数据库中存储序列化为字符串的数组将具有以下缺点(其中之一):

  • 当您需要更新设置时,必须先从数据库中提取当前设置,对数组进行反序列化、更改数组、对数组进行序列化并更新表中的数据。
  • 当搜索时,您将无法仅询问数据库是否给定用户(或一组用户)已禁用或启用给定设置,因此您将没有任何搜索的机会。

相反,您应该真正考虑创建另一个表,并将其作为与您其他表的一对多关系记录。这样,您不会有30个空字段,而是可以为与默认值不同的每个选项只有一行记录(请注意,此选项也具有一些缺点,例如如果更改了默认值)。

总之:如果您稍微关心上述缺点,我认为您应该避免将数组序列化并将其放入数据库中。


很好的回答。另外,如果你想在数据库中“存储数组”,你可能会喜欢研究一下ORM(对象关系映射),它可以使数据库访问以更面向对象的方式进行。Doctrine是PHP的一种ORM工具。不过要学习使用Doctrine并不容易。 - David Snabel-Caunt
问题在于连接操作可能非常昂贵,因此Web应用程序似乎经常避免多表连接。如果您要缓存对象或使用像Solr这样的搜索引擎(消除搜索问题),这一点尤其正确。 - Adam Gent
@Adam Gent:同意。没有通用的解决方案,但通常数据库应尽可能规范化。然而,正如你所提到的,当然也有将序列化、JSON化等数组放入数据库的情况。 - phidah

1

合适的方式(并非总是最好的方式)

CREATE TABLE mytable (
    myid INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
    mytitle VARCHAR(100) NOT NULL
);
CREATE TABLE myarrayelements (
    myarrayid INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
    myid INT UNSIGNED NOT NULL,
    mykey VARCHAR(100) NOT NULL,
    myval VARCHAR(100) NOT NULL,
    INDEX(myid)
);

$myarray = array();
$res = mysql_query("SELECT mykey, myval FROM myarrayelements WHERE myid='$myid'");
while(list($k, $v) = mysql_fetch_array($res)) $myarray[$k] = $v;

尽管有时将逗号分隔列表存储更方便。

0

有一件事是可扩展性有限。数据库不应与编程环境混合。此外,更改数据库中的值和调试要容易得多。数据库和CGI可以互换为另一个数据库或像Perl这样的CGI。


0
使用关系型数据库的原因之一是帮助维护数据完整性。如果你只是将一个序列化数组转储到表中的 blob 中,那么数据库无法检查该 blob 中的内容是否有任何意义。

0

你为什么不能把设置存储在服务器上的配置文件中呢?例如,我会将网站或应用程序的设置保存在config.php文件中,而不是数据库中。


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