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

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介:

本节书摘来自华章社区《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技术检索它们。

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
3月前
|
IDE PHP 开发工具
PHP中的类型提示与严格模式:提高代码可维护性
随着PHP语言的发展,开发者对代码的可读性、可维护性和可靠性有了更高的要求。PHP中的类型提示(Type Hinting)和严格模式(Strict Mode)为开发者提供了更强的类型检查机制,有助于提升代码质量和减少潜在的错误,尤其是在大型项目中。
|
11天前
|
关系型数据库 MySQL 网络安全
如何排查和解决PHP连接数据库MYSQL失败写锁的问题
通过本文的介绍,您可以系统地了解如何排查和解决PHP连接MySQL数据库失败及写锁问题。通过检查配置、确保服务启动、调整防火墙设置和用户权限,以及识别和解决长时间运行的事务和死锁问题,可以有效地保障应用的稳定运行。
65 25
|
4月前
|
存储 SQL 关系型数据库
PHP与数据库交互:从基础到进阶
【10月更文挑战第9天】在编程的世界里,数据是流动的血液,而数据库则是存储这些珍贵资源的心脏。PHP作为一门流行的服务器端脚本语言,其与数据库的交互能力至关重要。本文将带你从PHP与数据库的基本连接开始,逐步深入到复杂查询的编写和优化,以及如何使用PHP处理数据库结果。无论你是初学者还是有一定经验的开发者,这篇文章都将为你提供宝贵的知识和技巧,让你在PHP和数据库交互的道路上更加从容不迫。
|
1月前
|
存储 安全 API
陪玩平台中支付与结算模块的代码,陪玩系统数据库设计与代码实现
第三方支付平台对接涉及与微信支付、支付宝等API接口的调用,确保用户支付流程顺畅。结算模块根据业务规则计算陪玩师收益,强调安全性、异常处理、可扩展性和日志记录。数据库设计涵盖用户、陪玩者、订单等信息的存储管理,确保系统稳定运行。
|
2月前
|
PHP 开发者 容器
PHP命名空间深度解析:避免命名冲突与提升代码组织####
本文深入探讨了PHP中命名空间的概念、用途及最佳实践,揭示其在解决全局命名冲突、提高代码可维护性方面的重要性。通过生动实例和详尽分析,本文将帮助开发者有效利用命名空间来优化大型项目结构,确保代码的清晰与高效。 ####
76 20
|
3月前
|
供应链 安全 NoSQL
PHP 互斥锁:如何确保代码的线程安全?
在多线程和高并发环境中,确保代码段互斥执行至关重要。本文介绍了 PHP 互斥锁库 `wise-locksmith`,它提供多种锁机制(如文件锁、分布式锁等),有效解决线程安全问题,特别适用于电商平台库存管理等场景。通过 Composer 安装后,开发者可以利用该库确保在高并发下数据的一致性和安全性。
55 6
|
3月前
|
PHP 开发者 UED
探索PHP中的异常处理:提升代码的健壮性
在PHP开发中,优雅地处理错误和异常是确保应用稳定性和用户体验的关键。本文将通过深入浅出的方式,介绍如何在PHP中实现有效的异常处理机制,包括异常的基本概念、如何抛出和捕获异常,以及最佳实践。准备好让你的代码变得更加健壮和可靠吧!
36 2
|
2月前
|
SQL Java 数据库连接
JDBC编程安装———通过代码操控数据库
本文,教你从0开始学习JBCD,包括驱动包的下载安装调试设置,以及java是如何通过JBDC实现对数据库的操作,以及代码的分析,超级详细
|
3月前
|
SQL 关系型数据库 MySQL
12 PHP配置数据库MySQL
路老师分享了PHP操作MySQL数据库的方法,包括安装并连接MySQL服务器、选择数据库、执行SQL语句(如插入、更新、删除和查询),以及将结果集返回到数组。通过具体示例代码,详细介绍了每一步的操作流程,帮助读者快速入门PHP与MySQL的交互。
162 1
|
3月前
|
JSON JavaScript 关系型数据库
node.js连接GBase 8a 数据库 并进行查询代码示例
node.js连接GBase 8a 数据库 并进行查询代码示例

热门文章

最新文章