《PHP精粹:编写高效PHP代码》——2.7节设计数据库

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
云数据库 RDS MySQL Serverless,价值2615元额度,1个月
简介:

本节书摘来自华章社区《PHP精粹:编写高效PHP代码》一书中的第2章,第2.7节设计数据库,作者:(美)  Davey Shafik,更多章节内容可以访问云栖社区“华章社区”公众号查看

2.7 设计数据库
到目前为止,我们已经创建了两个非常基本的表并且看到如何使用PDO操作简单的数据。现在我们要扩展这些例子,添加一些另外的表,探讨我们如何在真实的应用程序中使用这些数据。让我们从图2.2开始,看看目前有什么。
图2.2显示了两张表以一对多的关系链接。这表明categories表中的每一个记录在食谱表中会有很多与之相关的记录;也就是说,一个类别会有很多食谱,但一个食谱只能属于一个类别。


7dda8d5b474be367b5566e9f4508e4433784918f

2.7.1 主键与索引
我们已经为两张表添加了主键,主键使我们提供的列在每个表中必定是唯一的,我们可以轻松访问一个特定的记录。此外还有一个好处,MySQL可以在该列放置一个索引(index)。添加一个索引至数据库的列和要求数据库保持对其中内容的跟踪一样。例如,如果你在recipes.name列上添加了一个索引,数据库使用该列会很容易找到项目,因为索引会保持对这些记录在什么地方进行跟踪。

2.7.2 MySQL解析
我们应该学习的最后一个数据库方法是MySQL EXPLAIN命令。EXPLAIN详细描述了MySQL将如何运行查询。在SELECT查询之前,我们通过迅速放置EXPLAIN术语来使用它:


ea3087770d8f634b63b46ae9e73c9a8b152bb2a8

这表明我们的查询不得不搜索所有的5个行,以便找到正在寻找的一行。五行并不是很多,但在这种情况下它们就是表中的每一行,并且总是带来坏消息!如果我们经常用食谱名查询食谱表中的行,我们可以添加一个索引来提高性能。
如果要添加一个索引,需使用ALTER TABLE语句。因此,要在recipes.name列添加一个索引,我们将输入:


26055c2e237033029ca7215067b41df364572a4b

这表明如果我们试图在recipes表中插入一个id为4的记录,我们将看到一个错误消息。
外键支持
请注意并非所有的数据库都支持外键。MySQL支持外键,但只支持InnoDB表类型。使用MyISAM表类型,你可以创建一个外键,但是它会被忽略!在phpMyAdmin中,当你创建一个表,你会发现一个标题为Storage Engine的下拉菜单,你可以通过其中的选项来选择一个InnoDB表类型。


5e6b96e1478b82481847d927a14dc88201ea96dd


573a16ef0bc27381165be8b1ad578d1f441ee85e

这是一个内部连接(inner join)的例子,这表明在这个查询中我们只能看到所有表中有匹配行的数据。我们在recipes表中还有其他的条目,但是因为我们仍需将一些配料和它们连接,所以这些条目不会在这个查询结果中出现。为了看到所有的食谱,无论它们有没有和配料连接,我们都将使用一个外部连接。
加入=内部连接
有时我们会看到只对自己使用JOIN关键字的查询,这些都是隐含的内部连接。这个例子使用了INNER关键字,让我们更清楚地看到发生了什么。我们很快将看到其他连接类型。

2.7.4 外部连接
现在你知道什么是内部连接了,你大概也猜到了什么是外部连接(outer join)。外部连接使我们能从一个表中检索所有行,还有其他表中与之匹配的行。如果没有匹配的数据,MySQL将对这些列返回NULL值。
由于外部连接包含的行来自于一个表及另一个随机的表,因此我们需要指定哪个表连接哪个表。我们使用RIGHT JOIN和LEFT JOIN表达式做到以上这些。因为我们是从左到右读,所以左边的表就是我们在SQL语句中遇到的第一个表。外部连接通常有助于勾勒出此时数据库的布局,或者你可以参考前面的架构图。
让我们来看看外部连接的一个例子。我们要显示所有的食谱,而不仅仅是带有配料的食谱。由于recipes表首先出现,因此我们将使用LEFT JOIN来表明需要显示左表中的所有行。


0b97ad13bd9848e58101dcf2f0e1a4d9d2af648a

要是愿意,我们可以从包含在查询中的任一表格提取很多列或几列。若在多个表中有相同名称的列,我们必须为这些列加上它们所属表名的前缀,否则MySQL会告诉我们它不知道所指的是哪一列。这是一个修饰所有列名的好办法,可以帮助明确数据来源。当你想要添加另一个表到你的查询中时,这可让你免于返回去重新修饰这些列名。

2.7.5 聚合函数和Group By
聚合函数(aggregate function)向我们提供了与查询相匹配的简要数据信息。我们用这种技术能达到各种理想的结果。这种精确的功能不同于平台到平台模式,这里有一些常见的例子以及它们的MySQL函数名:
对记录计数(COUNT)。
得到最大或最小的一个特定列的值(MAX或MIN)。
计算某一列的总和(SUM)。
计算某一列的平均值(AVG)。
例如,若想知道在查询中有多少条记录,可以使用MySQL中的COUNT()函数,就像这样:


3957702e11ab5fc9c8fddb4845764adb55a640fe

使用连接和聚合这两个函数的确非常棘手,但如果我们走一步看一步,对这些技术还是会慢慢理清头绪的。比起写一个庞大的SQL语句然后调试它,分阶段建立这些东西显然更加容易。
第一步是从一个表中得到数据并按照需要进行过滤。一次加入一个到表中,每次运行查询的时候,检查结果是否如你预期。一旦你看到MySQL根据请求算出的所有数据行,你就可以添加额外的格式化列、计算总数,以及其他任何需要为你应用程序生成的正确数据。使用聚合函数远比在PHP中为汇总数据集或计算平均数使用循环效率更高;数据库平台的确擅长处理数据,因此最好是把这些任务交给专家完成。

2.7.6 规格化数据
数据规格化的主题通常本身就可以构成一整章,但是,简而言之,使用这个方法的目标是:
按实体来拆分它们,并将拆分后的部分各自组成自己的表。
避免在一个列中有多个值。
在一个地方记录数据,并将其与其他数据连接。
按照现在的情况我们可以改善数据库设计,将chef列的数据移到一个单独的表中。每个厨师都有一个唯一的标识符,并且记录在recipes表中。由于厨师是一个实体,他应该有自己的表,在这里我们可以集中记录厨师的信息并且维护这些信息,而不是在每个recipe行中重复记录。
显而易见,如果允许用户输入名字会导致食谱表中出现很多个“John”,也许只有几个“John”,其中一些名字可能就是同一个人!为了避免发生这种情况,我们需要移动厨师到他们自己的表中,就像下面这样:


9fe4c6c768524f196dddd3822aa7c8976df3d43b

将数据分离进入表之后,我们给“厨师”这个实体建立了他们自己的表,这样可以避免在recipes表中重复记录值。这使我们更加接近最佳的标准化形式,并且巧妙地储存数据,允许我们使用本章前面读过的JOIN技术检索它们。

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
9天前
|
关系型数据库 MySQL Linux
【MySQL-10】数据库函数-案例演示【字符串/数值/日期/流程控制函数】(代码演示&可cv代码)
【MySQL-10】数据库函数-案例演示【字符串/数值/日期/流程控制函数】(代码演示&可cv代码)
【MySQL-10】数据库函数-案例演示【字符串/数值/日期/流程控制函数】(代码演示&可cv代码)
|
9天前
|
SQL 关系型数据库 MySQL
【MySQL-5】DDL的数据库操作:查询&创建&删除&使用(可cv代码+演示图)
【MySQL-5】DDL的数据库操作:查询&创建&删除&使用(可cv代码+演示图)
|
10天前
|
Java 关系型数据库 测试技术
Java代码一键生成数据库文档(案例详解)
Screw是一个自动化数据库文档生成工具,能根据数据库表结构快速生成简洁、多格式(HTML、Word、Markdown)的文档,支持MySQL、MariaDB等多数据库。它使用Freemarker模板,允许用户自定义样式。依赖包括HikariCP数据库连接池和对应JDBC驱动。通过在Java代码或Maven插件中配置,可方便生成文档。示例代码展示了如何在测试用例中使用Screw。文档效果依赖于数据库中的表和字段注释。
|
10天前
|
PHP 数据库
DIY私人图床:使用CFimagehost源码自建无需数据库支持的PHP图片托管服务-2
DIY私人图床:使用CFimagehost源码自建无需数据库支持的PHP图片托管服务
|
10天前
|
存储 PHP Apache
DIY私人图床:使用CFimagehost源码自建无需数据库支持的PHP图片托管服务-1
DIY私人图床:使用CFimagehost源码自建无需数据库支持的PHP图片托管服务
|
10天前
|
安全 关系型数据库 MySQL
【PHP开发专栏】PHP PDO与MySQLi操作数据库
【4月更文挑战第30天】PHP数据库交互的核心是PDO和MySQLi。PDO提供数据访问抽象层,支持多种数据库,强调安全和灵活性;MySQLi则专为MySQL设计,有面向对象和过程化接口。两者都支持预处理语句,防止SQL注入。选择取决于项目需求,如可移植性、特定功能和API偏好。了解其使用有助于编写安全高效的代码。
|
10天前
|
关系型数据库 MySQL PHP
【PHP 开发专栏】PHP 连接 MySQL 数据库的方法
【4月更文挑战第30天】本文介绍了 PHP 连接 MySQL 的两种主要方法:mysqli 和 PDO 扩展,包括连接、查询和处理结果的基本步骤。还讨论了连接参数设置、常见问题及解决方法,如连接失败、权限和字符集问题。此外,提到了高级技巧如使用连接池和缓存连接信息以优化性能。最后,通过实际案例分析了在用户登录系统和数据管理中的应用。
|
11天前
|
SQL 缓存 PHP
【PHP开发专栏】PHP数据库查询优化技巧
【4月更文挑战第29天】本文探讨了PHP数据库查询优化技巧,包括数据库设计的规范化与反规范化,合理使用索引,优化查询逻辑,以及避免SELECT *。在SQL查询优化中,利用EXPLAIN分析查询、优化JOIN操作和子查询,以及改进WHERE条件。PHP层面的优化涉及预处理语句、缓存查询结果、分页查询优化和异步处理。此外,还提到了高级技术如数据库分区、读写分离和分布式数据库。通过这些方法,开发者能提升查询效率,优化应用性能和用户体验。
|
11天前
|
SQL 关系型数据库 MySQL
【PHP开发专栏】PHP与数据库交互入门
【4月更文挑战第29天】本文介绍了PHP与数据库交互的基础,包括选择MySQL或PostgreSQL等关系型数据库,使用MySQLi或PDO扩展进行连接。示例展示了如何使用PHP连接数据库,如MySQLi的面向对象连接方式和PDO的多数据库支持。此外,还讲解了执行SQL查询(如SELECT、INSERT、UPDATE、DELETE)的操作,并强调了安全性与错误处理,如使用预处理语句防止SQL注入。通过学习,读者可掌握PHP操作数据库的基本技能。
|
1月前
|
安全 PHP 开发工具
php代码加密 php-screw-plus
php代码加密 php-screw-plus
25 0