网站建设咨询
138 0532 7355

2023-03-29 12:43:30

关于网站制作常用的MySQL 方面的教程

来源:东橙设计网站策划部

我们数字世界的支柱是一座不断增加的数据山。这意味着互联网和我们的网络世界的一个关键要素是利用像MySQL这样的数据库管理系统。

它们使我们能够以电子方式处理和存储大量数据。复杂的数据集可以很容易地细分为方便的子集并相应地使用。在我们的初学者MySQL教程中,我们将带您了解此数据管理系统的基础知识,并向您展示如何使用MySQL充分利用Web项目数据管理的示例。

什么是MySQL?

MySQL是全球最受欢迎的关系数据库管理系统之一,与Oracle和Microsoft SQL并列(查看 db-engines.com 以获取数据库模型流行度的当前排名)。该软件由瑞典公司MySQL AB于1994年开发,如今由甲骨文公司控制,并通过双重许可系统运行:除了专有的企业版本外,甲骨文还提供GPL许可的开源版本。

这种双重许可使公司有机会开发基于MySQL形成的应用程序,而不必遵守严格的许可。然而,Oracle对MySQL的收购在开源社区遭到了一些激烈的批评。

MySQL是用C和C++编写的,并有一个基于Yacc的SQL解析器,带有一个私人开发的分词器(词法扫描器)。数据库管理系统以其对不同操作系统的广泛支持而闻名。

MariaDB – 具有潜力的MySQL分叉

将MySQL项目纳入Oracle产品组合主要在开发人员领域遭到不信任和批评。这主要是由于GPL许可的MySQL版本和付费企业产品之间的差异正在逐渐增加。数据库管理系统的新功能越来越多地仅在软件的专有版本中提供。未发布的错误数据库和缺乏测试也表明,开源项目现在被软件巨头甲骨文控制着,因此它被忽视了。因此,开源社区内部的支持正在减弱。

早在2009年,支持MySQL创始人Michael 'Monty' Widenius的核心开发团队就开始背弃流行的数据库系统,并开始专注于使用MariaDB启动该软件的开源分支。到2012年底,Fedora,OpenSUSE,Slackware和Arch Linux成为第一个从MySQL切换到MariaDB作为标准安装的Linux发行版。许多开源项目,以及大牌软件公司和网络平台,都遵循了这个例子——其中包括Mozilla、Ubuntu、Google、Red Hat Enterprise Linux、Web of Trust、Team Speak、维基百科基金会和前面提到的软件项目XAMPP。

很明显,MariaDB的开发比开源MySQL版本更频繁。因此,可以安全地假设分叉将很快超过其母项目。

数据库系统

在现代世界中,电子数据管理通常发生在数据库系统(DBS)中。DBS 由两个基本组件组成:数据库 (DB) 本身和管理数据所需的数据库管理系统 (DBMS)。

  • 数据库管理系统:DMBS是类似于MySQL的软件,负责管理数据库。该管理软件的任务之一是根据预定义的数据库模型构建数据。此外,DBMS 控制对数据库的写入和读取访问,管理大量数据和对并行数据库的访问,并确保遵守数据完整性、数据保护和数据安全策略。
  • 数据库:数据库是内容相似的数据集合,如客户数据或 CMS 数据。一个 DBMS 可以同时管理多个数据库。

下图显示了数据库系统的示意图:



关系数据库模型

MySQL是关系DBMS的定义。这意味着数据管理是使用基于表的数据库模型来组织的。MySQL处理的所有数据都存储在一个表中,该表可以根据进行关联。

我们将通过一个简单的示例来演示它是如何工作的。下面是两个表格,“作者”和“作品”。

关系数据库中的所有表都包含列和行。表的每一都包含一个特定属性。在“作者”表中,有包含属性“author_id”、“名字”和“姓氏”的列。表的包含数据记录。这些通常通过主键单独标识。哪个属性是主键,由表的创建决定。这样做的要求是主键启用对数据的唯一评估。因此,列中的每个主键只能使用一次。建议使用 ID 对它们进行编号。

除了主键work_id之外,我们的表还包括author_id作为外键。这在两个表之间创建了关系,并使我们能够将记录从一个表链接到另一个表。如果连接了关系数据库的两个表,则称为连接。这可以通过调用这样的命令来实现:“作者约翰·罗纳德·鲁埃尔·托尔金的所有作品,包括他们的首次出版日期”。

托尔金列在作者表中,主键author_id1。要调用作者的所有作品,我们可以简单地使用 Works 表中的外键。这使我们能够检索链接到author_id1的所有行。

在实际使用中,MySQL数据库操作使用标准化的SQL命令,如选择,插入,更新和删除。我们将在 MySQL 教程的以下部分中更详细地探讨这些内容。

当然,我们可以将作者及其作品的所有数据存储在一个表中。但这会导致数据库包含大量冗余条目,因为我们必须为每一行填写名字和姓氏表,即使许多会重复。这也给数据库内存带来了额外的压力,这意味着如果您希望更新表,则需要单独更新每一行,而不是能够一次性更改整个数据集。因此,大多数开发人员在使用关系数据库系统时会坚持每个表一个主题焦点。这称为数据规范

MySQL的中心应用领域是存储动态网页的数据。MySQL与Web服务器软件Apache和脚本语言PHP或Perl的结合已被确立为Web开发的经典软件框架。这个Web堆栈被称为LAMP(Linux),MAMP(MacOS)或WAMP(Windows),这取决于它使用的服务器操作系统。

但是对于MySQL初学者,我们建议使用本地文本环境XAMPP,以获得这个复杂的数据库管理系统的第一手经验。这使用当前版本的MariaDB。

安装数据库管理系统

为了带您了解 MySQL 的基础知识,我们将使用实际示例。我们的MySQL介绍将基于测试环境XAMPP工作。代码片段和屏幕截图将集中在通过PHP在本地Windows计算机上的Apache HTTP服务器的帮助下实现的数据库操作上。我们将使用分支MariaDB,而不是经典的MySQL数据库。但别担心 - 这两个数据库管理系统都非常兼容,您将能够通过 1:1 翻译直接复制您学到的所有内容。因此,对于本初学者教程而言,您使用的是MySQL还是MariaDB,这没有什么区别。

我们的 XAMPP 教程演示了如何在 Windows 计算机上本地安装测试环境。如果您想从一开始就学习如何处理关系数据库,我们强烈建议您直接掌握MariaDB。基于MySQL的替代测试环境以AMPPS的形式存在,也免费提供。

也可以使用用户定义的 Web 堆栈。MySQL和MariaDB可以与一系列不同的操作系统,Web服务器和脚本语言结合使用。您可以在 mysql.com 和 mariadb.com 免费访问 GPL 许可的下载包。不同平台的详细安装教程可以在MySQLMariaDB的文档中找到。

使用 phpMyAdmin 进行数据库管理

在管理MySQL时,我们将在这里使用免费的Web应用程序phpMyAdmin。这是 XAMPP 软件包安装的一部分,但也可以从官方项目网站免费下载单独的下载包

phpMyAdmin被认为是在线管理MySQL数据库的标准软件。这个用PHP和JavaScript编写的Web应用程序提供了一个用于执行数据库操作的图形用户界面。这允许用户在 Web 浏览器中轻松创建和管理关系数据库的表。也不需要事先了解相应的 SQL 命令。

调用 phpMyAdmin

安装软件包XAMPP后,您可以通过控制面板启动数据库管理系统(MySQL或MariaDB),其方式与测试堆栈的其他组件相同。转到“操作”菜单,然后选择“开始”按钮。要在Web浏览器中调用phpMyAdmin,您需要启动Web服务器Apache。激活的模块将在 XAMPP 控制面板中以绿色突出显示。您还可以通过文本窗口中的通知查看 XAMPP 模块的当前状态。

事实

XAMPP是作为软件项目“Apache Friends”的一部分开发的。它被设计为一个紧凑的测试系统,用于本地计算机。此软件包不是为联机准备 Web 服务而设计的。由于其许多局限性,生产系统XAMPP不应被视为安全使用。

在本地托管文件夹中,您可以在以下位置访问此管理软件的 Web 界面

localhost/phpmyadmin/

.

一旦您在MySQL安装中为root帐户定义了密码,phpMyAdmin就会要求您在登录屏幕上提供此信息。如果您将phpMyAdmin用于网络托管项目,那么您相应的登录数据将被分配给相应的提供商。在这些情况下,您通常没有任何权限。

成功登录后,phpMyAdmin将显示应用程序的起始页。这将使您有机会对MySQL连接的字符集(排序规则)以及所需的显示模式(语言,设计和字体大小)进行基本设置。

在右侧,您还可以找到数据库服务器的关键数据概述,您选择的Web服务器软件,以及有关phpMyAdmin当前版本的信息。与应用程序中的所有其他菜单列表一样,起始页上的菜单列表以选项卡的形式布局。选项包括“数据库”、“SQL”、“状态”、“用户帐户”、“导出”、“导入”、“设置”、“复制”、“变量等选项卡。

在用户界面的左侧,您将找到一个导航面板。这里列出了所有表,您可以使用这些表在phpMyAdmin的帮助下访问数据库。在左上角,在程序徽标下方,该软件提供了指向主页以及官方文档的链接。此外,您还可以配置导航面板并更新您的个人显示器。

我们将通过向您展示如何设置您的第一个数据库来开始我们的 MySQL 教程。

设置数据库

为了使用phpMyAdmin设置数据库,接下来您应该在主页的菜单栏中选择“数据库”选项卡。

在“创建数据库”字段中输入所需的数据库名称,然后选择一个字符集。我们建议使用排序规则utf8mb4_unicode_ci。通过选择字符集,可以让数据库服务器知道应为将发送给您的文件使用哪种编码。mb4 变体甚至允许使用符号或表情符号等异国情调的字符,因为它们位于 Unicode 平面(基本多语言)之外,因此强烈建议使用。

通过单击“创建”确认您的输入。您新创建的数据库将显示在屏幕左侧的导航面板中。最初,新创建的数据库将不包含任何内容。为了开始存放文件,接下来您需要创建一个表。

创建表

要创建新表,请选择所需的数据库,然后选择菜单选项卡“结构”。

通过在“创建表”选项卡下输入名称(例如用户)以及所需的列数来设置创建表。请记住,每列表示数据集的一个属性。如果需要其他列,可以在以后添加这些列。

例如,如果您希望为您的网站创建用户数据库,则表上的列可以使用以下名称:

描述
编号 每个用户唯一的标识号
名字 用户的名字
用户的姓氏
电子邮件 用户的电子邮件地址
密码 用户的密码
created_at 上市的日期和时间
updated_at 商品信息更新的日期和时间

因此,对于您的用户数据库,您可以创建一个由七列组成的表用户。然后可以通过单击“Go”来确认。

创建表后,phpMyAdmin 允许您命名各个表列以及决定所涉及的数据的格式设置。

下表中提供了可能的表结构格式的说明。

选择 描述
名字 数据库表的每一列都将分配一个名称,并且可以在一定的限制内自由选择这些名称。任何字母(大写或小写)、数字、美元符号和下划线都没有问题。然后,这些可以用作不允许的空格的替代项(正确:user_id;不正确:用户 ID)。列名不能仅由数字组成。此外,SQL 数据库语言中还有为某些角色和功能保留的各种关键字。这些列表可以在MySQL文档中找到。实际上,可以通过在相应列中放置反引号 ('') 来绕过这些限制中的大多数。相同的规则适用于 MySQL 中的表和其他名称。建议您使用与相应属性相关的英文列名称。
类型 数据类型指示列中保存的文件类型。MySQL和MariaDB使您可以根据整数和浮点数,时间和日期以及文本字符串和二进制数据定义文件。可以在数据类型表中找到说明。
长度/值 对于某些数据类型(例如文本字符串),可以为列的值分配最大长度。
违约 “默认”选项允许您为列设置标准值。然后,如果数据集不包含特定列的值,则会自动插入该值。
整理 使用“排序规则”选项,您可以为列分配特定的字符类型。然后,这可以不同于全局数据库设置。还可以更改所有列的表范围的编码。
属性 某些数据类型可以通过可选属性更详细地指定。例如,这意味着使用有符号和无符号属性,您可以设置整数或浮点图形是否可以接受负(有符号)或仅接受正(无符号)值。
指数 索引规则可以通过使用“索引”选项来设置。如果为一列选择索引设置 PRIMARY,则会将其设置为表的主键。Die UNIQUE 设置确定此列中的值只能保存一次。这确保了没有重复的危险。
A_I 缩写“A_I”代表AUTO_INCREMENT,如果数据集创建过程中未指定任何值,则指示数据库管理系统自动提出一个值。此选项可以通过数据集的索引来访问。
评论 “注释”字段允许您为表格列分配注释。

此处概述的选项涵盖了形成表列的最重要设置。如果您使用滚动条进一步向右滚动,您将找到更多设置。这些内容未在本面向初学者的 MySQL 教程中介绍。

下表列出了可以使用MySQL和MariaDB处理的不同类型的数据,以及它们的值范围和存储要求。

类型 描述 值范围 存储要求
天因特 非常小的整数 无符号:0 到 255 签名:-128 到 +127 1 字节
斯莫林特 小整数 无符号:0 到 65.535 符号:-32.768 到 +32.767 2 字节
MEDIUMINT 中等大小的整数 无符号:0 到 16.777.215 签名:-8.388.608 到 +8.388.607 3 字节
整数/整数 正常大小的整数 无符号:0 到 4.294.967.295 签名:-2.147.483.648 到 +2.147.483.647 4 字节
比金特 大整数 无符号:0 最多 18.446.744.073.709.551.615 签名:-9.223.372.036.854.775.808 到 +9.223.372.036.854.775.807 8 字节
具有单精度的浮点图 无符号:0 到 3,4e+38 有符号:-3,4e+38 到 3,4e+38 4 字节
双精度浮点图 无符号:0 到 3,4e+38 有符号:-3,4e+38 到 3,4e+38 8 字节
日期 日期格式“年-月-日” '1000-01-01' 至 '9999-12-31' 3 字节
时间 时间格式 'HH:MM:SS.SSSSSS' '-838:59:59.999999' 到 '838:59:59.999999' 3 字节
日期时间 日期和时间格式 'YYYY-MM-DD HH:MM:SS.SSSSSSS' 包含日期和时间(最多 23:59:59.999999 眩晕) 8 字节
时间戳 格式为“YYYY-MM-DD HH:MM:DD”格式的时间戳 '1970-01-01 00:00:01' (UTC) 至 '2038-01-19 05:14:07' (UTC) 4 字节
从1901年到2155年的一年 1901 至 2155 和 0000 1 字节
固定长度字符串;M 表示列长度(以字符为单位) 对于 M:0 最多 255 个字符 M 字节
瓦查尔 可变长度字符串;M 表示列长度(以字符为单位) 对于 M:0 最多 65.535 个字符 最大 M + 2 字节
小文本 长度可变的非常小的字符串;M 表示列长度(以字符为单位) 对于 M:0 最多 255 个字符 M + 1 字节
发短信 可变长度字符串;M 表示列长度(以字符为单位) 对于 M:0 最多 65.535 个字符 M + 2 字节
中文本 可变长度的中型字符串;M 表示列长度(以字符为单位) 对于 M:0 到 16.777.215 个字符 M + 3 字节
长文本 长度可变的长字符串;M 表示列长度(以字符为单位) 对于 M:0 到 4.294.967.295 个字符 (4 GB) M + 4 字节
斑点 BLOB(二进制大对象)是具有可变长度文件(例如图像、音频)的二进制对象。 最大长度 M: 65.535 字节 M + 2 字节
TINYBLOB 具有可变长度文件的小二进制对象。 最大长度 M: 255 字节 M + 1 字节
MEDIUMBLOB 具有可变长度文件的中型二进制对象。 最大长度 M: 16.777.215 字节 M + 3 字节
长斑点 具有可变长度文件的大型二进制对象 最大长度 M:4.294.967.295 字节 (4 GB)。 M + 4 字节
ENUM (额外费用) 字符串对象,其允许值是在创建列时定义的。 最多 65,535 种不同的元素 1 或 2 字节,取决于可能值的数量
设置 字符串对象,其允许值是在创建表时定义的。可以选择多项选择。 最多 64 个不同的值 1、2、3、4 或 8 字节,具体取决于可能值的数量

为我们的示例表用户确定了以下设置:

列 id 的可能值被选为整数 (INT),并带有属性 UNSIGNED。 这意味着 id 只能接受正数值。在“索引”中,我们为id选择了“主要”设置。 标识号在此处用作表用户的主。 “A_I”Auto_Increment)旁边的勾号表示数据库管理系统知道每个输入的ID应自动生成为序列号。

名字姓氏电子邮件密码列的值被选为数据类型 VARCHAR。 这意味着我们正在处理一个字符串,我们使用选项“长度/值”将其长度 (M) 限制为 50 个字符。关于电子邮件列,索引选项UNIQUE已被激活。这使我们能够确保表中的每个电子邮件地址仅保存一次。

对于created_atupdated_at列,已选择数据类型 TIMESTAMP。数据库管理系统保存与时间相关的数据,以便以 YYYY-MM-DD HH:MM:DD 格式创建和更新数据集。鉴于系统为每个新条目自动生成时间戳,我们为created_at列选择标准值CURRENT_TIMESTAMP。这意味着只有当我们决定更新条目时,updated_at才会变得相关。因此,我们允许此列使用 null 值,并将 NULL 设置为标准

事实

在 PHP 中,NULL 值被描述为一个空条目。如果尚未为空字段赋值,则该空字段的值为 NULL

存储引擎方面,我们使用MySQL标准电子表格表格格式InnoBD。

通过图形用户界面应用的所有表格设置都由phpMyAdmin转换为SQL代码。如果需要,可以通过单击“SQL 预览”选项卡来显示这些内容。

CREATE TABLE test.users ( id INT UNSIGNED NOT NULL AUTO_INCREMENT , forename VARCHAR(50) NOT NULL , surname VARCHAR(50) NOT NULL , email VARCHAR(50) NOT NULL , password VARCHAR(50) NOT NULL , created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP , updated_at TIMESTAMP NULL DEFAULT NULL , PRIMARY KEY (id), UNIQUE (email)) ENGINE = InnoDB;

有关 SQL 语法的详细说明,请参阅下面的数据库查询部分。

只需单击“保存”,您就可以保存您的设置。表用户显示在数据库测试下的导航面板中

管理表

要管理您创建的表,请在导航面板中单击该表的名称。在“浏览”选项卡下,phpMyAdmin提供了存储在相应表中的数据的概述。在我们的示例表中,此请求返回一个空结果,因为到目前为止,用户表中没有数据集。

管理数据表时,导航栏提供了多个选项卡。如果您希望更改数据表的结构,请单击“结构”选项卡。可以在“插入”选项卡下添加新数据集。此外,phpMyAdmin使您可以搜索表,管理授权,以及导出数据集,甚至从其他表中导入数据集。

编辑表结构

如果您希望在稍后阶段向表中添加其他列,删除现有列,甚至编辑已经存在的列,只需单击标有“结构”的选项卡即可完成。

转到“添加列”,然后选择所需数量的新列以及它们应具有的相应位置。

下图显示了在updated_at之后插入的列:

如果您希望删除列,可以通过勾选列旁边的框,然后向下滚动并单击“删除”来完成。

可以通过单击“更改”按钮来编辑列。您将被带到一个编辑视图,您已经从创建表格中识别出该视图:

在某些情况下,对表结构的更改可能会导致数据的结果。在开始编辑或删除已创建的列之前,绝对应该确保备份数据库。如果您移动到标题为“出口',请选择所需的备份文件格式,然后单击”Go'进行确认。这将打开对话框窗口,您的 Web 浏览器将在其中查询下载的保存位置。通过phpMyAdmin进行数据库备份的替代方案由备份程序MySQLDumper提供。

创建表条目

有两种可能性可以通过phpMyAdmin用数据填充您的表格。您可以从外部文件(例如,从备份)导入数据集,也可以手动创建表条目。只需选择示例表用户,然后单击“插入”选项卡。

phpMyAdmin 显示以下数据输入字段:

在“列”下,将列出分配给表用户的各个列。在“类型”下,您将找到与分配给每列的数据类型以及字符限制(在括号中)有关的信息。在这种情况下,我们跳过“功能”区域并直接转到“值”。在这里,我们定义示例表中各个列的值。

在上一章中,我们配置了表用户,使数据库管理系统将自动填充 idcreated_at 和 updated_at 列的数据字段。id 列将看到按顺序分配给每个新条目的标识号。created_at字段将自动分配最新的时间戳,对于updated_at,系统将分配标准值 NULL。这意味着最初必须手动输入名字姓氏电子邮件密码列的数据。我们在这里用虚构的用户详细信息来说明这一点:

  • 名字:约翰
  • 姓氏: 多伊
  • 电子邮件: john@doe.com
  • 密码: QWERTY

单击“Go”后,您将数据传输到表中。然后,phpMyAdmin 将自动更改为“SQL”选项卡,并以 SQL 语法将执行的数据库操作显示为语句:

INSERT INTO users (id, forename, surname, email, password, created_at, updated_at) VALUES (NULL, 'John', 'Doe', 'john@doe.com', 'qwertz', CURRENT_TIMESTAMP, NULL);

一般来说,您可以通过图形用户界面轻松执行的所有数据库操作也可以用数据库语言SQL编写。这是 Web 开发环境中的标准过程。

所谓的SQL查询可以在所有动态Web应用程序的源代码中找到,并使Web服务器能够与数据库进行交互。这意味着数据库语言SQL基于命令 - 例如,检索数据并在程序执行的上下文中使用它们。最重要的SQL顺序SELECTINSERT,DELETEUPDATE以及基本数据库操作的语法是我们MySQL教程下一章讨论的主题。

接下来,我们用更多的用户数据填充用户表,并查看“浏览”选项卡中的表概述:

通过单击相应的列名称,您可以将表格按所需顺序排序。

建立数据库连接

在我们用条目填充示例表用户之后,下一章将讨论如何通过 Apache Web 服务器通过 PHP 检索存储的文件。

执行此操作的第一步是设置数据库连接。为此,PHP中提供了三个接口函数:MySQL扩展,MySQL改进扩展(MySQLi)和PHP数据对象(PDO)。

  • MySQL 扩展:MSQL扩展是指曾经非常流行的MySQL接口,但今天已经过时了。与MySQLi和PDO相比,旧的MySQL扩展处于劣势,因为它不支持预准备语句或命名参数。
  • MySQLi:这是用于访问MySQL数据库的经典PHP扩展的改进版本。该接口既有过程功能,也有面向对象的功能。使用仅限于MySQL和MariaDB数据库。
  • PDO:PHP 数据对象 (PDO) 是一个面向对象的接口,为数据访问提供抽象层。这意味着通过PDO不仅可以集成MySQL数据库,还可以集成PHP中的PostgreSQL,Oracle,MSSQL或SQLite等其他数据库系统。

在本MySQL课程中,我们将其限制为通过PDO的数据库连接。

为了能够对数据库进行 PHP 脚本查询,必须首先对其进行身份验证。可以使用以下代码行设置通过 PDO 的数据库连接:

<?php
$pdo = new PDO('DSN', 'username', 'password');
?>

建议您在包含数据库操作的每个脚本的开头包含此信息。

我们使用 PHP 关键字 new 来创建 PDE 基本类实体。构建它需要三个参数;数据源名称 (DSN)、用户名和数据库密码(如果适用)。在这种情况下,DSN 由以下参数组成:

  • PDO数据库驱动:mysql
  • 数据库服务器(主机=):本地主机
  • 数据库名称(dbname=):test
  • 字符集字符集=):utf8

如果您没有为数据库指定任何登录详细信息,则可以输入用户名 root 并将密码字段留空:

<?php
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root', '');
?>

数据库连接保存在变量$pdo中。这样就可以在程序代码的稍后时间点回引用数据库连接。

如果建立了与数据库的连接,则可以在后续脚本代码中向数据库发送任意数量的查询。脚本终止后,数据库连接也会停止。

使用选择、插入、更新和删除进行数据查询

为了从我们的数据库中检索文件,我们参考数据库语言SQL。这在语义上基于英语,并故意保持相当简单。SQL 语法在很大程度上是不言自明的。

在 SQL 中,您可以使用语句,这些语句也称为查询或请求。

例如,基本 SELECT 查询由以下组件组成:

SELECT column FROM table;

接下来,您需要指定 SQL 命令 SELECT,然后指定该命令应引用的各种列和表。然后,分号使语句结束。

此外,您还可以扩展语句以包含可选条件,如排序或分组函数:

SELECT column FROM table WHERE condition ORDER BY sortingsequence;

约定是 SQL 命令大写,而数据库、表和字段名以小写形式编写。这只是为了使它们更具可读性。SQL主要是一种无格式的语言,因此不区分大写和小写。

如果您决定使用已经预定义的相应 SQL 关键字的表名和列名(不建议这样做),则必须将它们放在反引号 ('') 中。

下面我们使用命令 SELECTINSERT、UPDATE 和 DELETE 的示例演示基本 SQL 语句的语法。

选择

命令 SELECT 用于从所需数量的表中检索选定的数据行。例如,如果您希望在 Web 浏览器中显示前面提到的表中所有用户的姓名和姓氏以及电子邮件地址,您应该在 XAMPP 环境的 htdocs 目录中创建一个新的 PHP 文件文本.php然后输入以下脚本:

<?php
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root', '');
$sql = "SELECT forename, surname, email FROM users";
foreach ($pdo->query($sql) as $row) {
   echo $row['forename'] . " " . $row['surname'] . "<br />";
   echo "E-Mail: " . $row['email'] . "<br /><br />";
}
?>

示例代码可以按如下方式阅读:首先,我们从具有 PHP start 标记 <?php 的脚本开始。在第 2 行中,我们在 localhost 上建立与数据库测试的连接,并将其保存在变量 $pdo 中。带有命令 SELECT 的 SQL 语句可以在第 3 行找到。在这里,指示数据库管理系统从用户表中检索列名、姓氏电子邮件。然后,我们将语句保存在 $sql 变量中。

第 4 列到第 7 列显示 foreach 循环。这提供了遍历任何数组的可能性,例如逐步遍历数据结构。选择要迭代的数组以及如何保存请求的文件可以在 foreach 构造后面的括号中指定:

$pdo->query($sql) as $row

$pdo变量通过第 2 行中建立的连接响应所需的数据库。我们将其与函数 query() 一起发送到存储在变量 $sql 中的 SQL 语句

这里发生的情况是,Web 服务器从数据库中检索用户表的列名字、姓氏电子邮件,并在 foreach 循环的框架内遍历每个单独的表行。 至于提取的数据应该保存在哪里,这是由 PHP 关键字指定的,就像在数组$row变量中一样

这是数组在 foreach 循环的第一轮中的样子:

$row = array (
    forename => John,
    surname => Doe,
    email => john@doe.com
)

在当前示例中,foreach 循环的一部分也是每次循环传递期间通过 echo 输出的文本。这意味着我们单独浏览 users 表的每一列,分别读取 SQL 语句中定义的列的存放文件,然后通过 Web 浏览器释放它们。

如果应通读表的所有列,则应在 SQL 语句中使用星号作为占位符

<?php
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root', '');
$sql = "SELECT * FROM users";
foreach ($pdo->query($sql) as $row) {
   echo $row['forename'] . " " . $row['surname'] . "<br />";
   echo "E-Mail: " . $row['email'] . "<br />";
   echo "Created at: " . $row['created_at'] . "<br /><br />";
}
?>

此外,我们还可以将存储在用户中的所有数据用作脚本的一部分。下面的屏幕截图显示了带有附加时间戳的文本,该时间戳指示记录数据的时间:

In the case of both previous examples, the web server gives us the user details in the order in which we originally entered them in the users table (according to the ID). If you wish to sort the data in a different order, you can do this through the use of the SQL keyword ORDER BY. The following example will show the data being organized according to alphabetical order of users’ first names:

<?php
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root', '');
$sql = "SELECT forename, surname, email FROM users ORDER BY forename";
foreach ($pdo->query($sql) as $row) {
   echo $row['forename'] . " " . $row['surname'] . "<br />";
   echo "E-Mail: " . $row['email'] . "<br /><br />";
}
?>

插入

通过phpMyAdmin创建数据库条目的情况很少发生。通常,作为Web服务器执行脚本的一部分的数据写入数据库中,例如,当互联网用户在网站上填写在线公式或客户在互联网商店的网站上发表评论时。在这两种情况下,SQL 命令 INSERT 都部署在后台。根据以下模式创建带有命令 INSERT 的 SQL 语句:

INSERT INTO table (column1, column2, column3) VALUES (value1, value2, value3);

这可以读作如下:调用命名表,然后在第 1、2 和 3 列中输入值 1、2 和 3。

一个基本的 PHP 脚本,用于将进一步的数据集添加到我们的示例表中,可能如下所示:

<?php
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root', '');
$sql = "INSERT INTO users (forename, surname, email, password) 
VALUES ('Paddy', 'Irish', 'paddy@irish.com', 'qaywsx')";
if ($pdo->exec($sql) === 1)
  echo "New record created successfully";
?>

接下来,我们开始构建与数据库的连接,并将其保存在变量 $pdo 中。最后,我们指定 SQL 语句并将其保存到变量 $sql。 在第 5 列中,我们使用箭头 (->) 来访问变量 $pdo,然后在函数 exec() 的帮助下,执行存储在 $sql 中的 SQL 语句

为了确保我们的脚本只在 users 表中输入一个数据集,我们需要检查受影响的列数。这可以在 if 条件的帮助下完成。这样做是确保如果输入的数据集数为 1,则只能显示在 Web 浏览器中成功创建的字符串新记录。如果再次执行案例,则消息保持不变。由于价值电子邮件已被定义为唯一,因此可以避免重复的条目

如果我们在数据库中调用示例表用户的概述,我们会看到该表已扩展为包含数据集 5。按照预期,然后自动添加顺序标识号和时间戳。

更新

如果要更新现有数据集,请根据以下基本架构使用 SQL 命令 UPDATE

UPDATE table SET column1 = value1, value2 = value2 WHERE column3 = value3

翻译成简单的英语,此语句的意思是:选择指示的表,并将列 1 中的值替换为 Value1,将列 2 中的值替换为值 2,前提是列 3 包含值 3。注意:如果您忘记了条件,MySQL将覆盖所有数据集中受影响的字段。

在此示例中,我们正在处理将数据库操作链接到条件的 SQL 语句。转移到我们的示例表中,用户 John Doe 的电子邮件地址可以通过以下 PHP 脚本更新:

<?php
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root', '');
$sql = "UPDATE users 
SET email = 'john.doe@example.com', updated_at = NOW() WHERE id = 1";
if ($pdo->exec($sql) === 1)
  echo "Update successful";
?>

在 SQL 语句中,我们明确指定电子邮件列中的当前值将被新值 john.doe@example.com 替换,前提是列 id 的值等于 1。有了这个,我们只需使用主键 1 更新数据集。此外,在同一语句中,我们还在 MySql 函数的帮助下更新了列updated_at的值,该函数还为其提供了更新的时间戳。然后像以前一样在 if 条件的框架内使用代码行 $pdo->exec($sql) 执行 SQL 语句。

假设更新成功,phpMyAdmin 应该出现在更新表的“浏览”选项卡中:

在此示例中,我们更新了一个电子邮件地址,并将列中的标准值 NULL 替换为时间戳updated_at。此外,UPDATE 命令还可以将值从一列传输到另一列。可以通过使用 email_registration 列扩展示例表用户来执行此操作。这使我们可以区分两个电子邮件地址;无论是注册期间使用的内容,还是当前的联系地址,可能会随着时间的推移而变化。最初,两个地址将显示相同,以便可以将值从一个字段传输到另一个字段。为此,我们使用phpMyAdmin和“结构”选项卡中的“添加列”选项,然后最初创建一个新列email_registration

使用以下 UPDATE 语句传输值:

UPDATE users SET email_registration = email

鉴于我们希望更新所有数据集,因此我们不概述此更新的任何条件:

<?php
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root', '');
$sql = "UPDATE users SET email_registration = email";
$affected = $pdo->exec($sql);
echo "$affected rows updated<br>";
?>

如果脚本通过 Web 浏览器执行,数据库管理系统会将所有数据集的值从电子邮件列传输到email_registration列。

删除

可以使用 SQL 命令 DELETE 删除数据库条目。 可以使用以下架构进行部署:

DELETE FROM table WHERE column = value

如果您正在使用数据库中的 ID,则有可能标识要删除的条目。例如,如果您希望删除示例表中的第 5 项,请输入以下内容:

<?php
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root', '');
$sql = "DELETE FROM users WHERE id = 5";
$affected = $pdo->exec($sql);
echo "$affected rows updated<br>";
?>

SQL 命令 DELETE 总是删除完整的数据库列。如果只想删除数据库某些列中的值,可以使用 UPDATE 语句执行此操作。更新表设置列 = 空,其中...您可以将值 NULL 分配给列,当然前提是您已为相关列授权了 NULL 值。

准备好的发言稿

PDO允许将数据库操作转换为所谓的预准备语句。如今,这种“先入为主的查询”是Web开发领域的标准做法,因此受到所有现代数据库管理系统的支持。

在前面的示例中,我们直接在 SQL 语句中传输参数值。但是,预准备语句使用占位符,然后仅随后为占位符赋值。这使得数据库管理系统可以在处理参数之前检查参数的有效性。这可以作为防止 SQL 注入的有效保护。对于这种攻击模式,黑客创建或更改SQL命令,以便访问敏感数据,覆盖数据或将自己的命令合并到系统中。

SQL 注入基于 SQL 数据库领域的已知安全漏洞。例如,如果用户的条目通过 $_GET 使用静态参数传输,则黑客有机会用元字符来增加输入。如果他们设法进入 SQL 解释器而不屏蔽,这可能会导致不良影响。使用参数化查询可以有效避免这种情况。这样,预准备语句充当 SQL 命令的 SQL 命令的模板,这些命令与实际参数分开传输到数据库。这不仅会验证传输的数据,还可以自动屏蔽元字符,并将参数插入到 SQL 语句中,而不是占位符中。

除了这些安全功能外,预处理语句还具有性能优势。当使用各种参数在循环中运行相同的 SQL 命令时,这一点变得很明显。一旦预准备语句被解析一次,它就会保留在数据库系统中,只需要使用新参数来实现。这意味着复杂的查询会大大加快。

在PDO中,准备语句是在函数prepare()的帮助下实现的。 这将为执行准备一个语句,并返回一个语句对象。问号 () 或命名参数将用作相应值的占位符。

具有未命名参数的预准备语句

下面的代码示例将数据库操作 INSERT 显示为具有未命名参数的预准备语句:

<?php
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root', '');

// prepare SQL statement 
$statement = $pdo->prepare("INSERT INTO users (forename, surname, email, password) 
VALUES (?, ?, ?, ?)");

// bind parameter 
$statement ->bindParam(1, $forename);
$statement ->bindParam(2, $surname);
$statement ->bindParam(3, $email);
$statement ->bindParam(4, $password);

// insert data sets
$forename = "Anders";
$surname = "Andersen";
$email = "anders@andersen.com";
$password = "mnbvc";
if ($statement->execute())
  echo "New record $forename created successfully<br>";

$forename = "Matti";
$surname = "Meikäläinen";
$email = "matti@meikäläinen.com";
$password = "jhgfd";


// display status
if ($statement->execute())
  echo "New record $forename created successfully<br>";
?>

接下来,在 prepare() 函数的帮助下,我们创建所需查询的语句对象,然后将其保存在 $statement 数组中。问号不是具体的参数值,而是部署为占位符。

如果语句仅包含占位符,则必须将以下代码中单独传输的值绑定到该语句。在 PHP 中使用 bindParam() 函数。我们使用箭头运算符 (->) 访问 $statement 对象的 bindParam() 方法,然后分配这个变量(1 对应于第一个问号,2 对应于第二个问号,依此类推)。

然后,可以使用所需的参数根据需要随时执行此 SQL 模板。在当前示例中,我们为两个数据集指定变量值。这些预先设想的 SQL 语句的执行是通过 execute() 对每个数据集进行的。

具有命名参数的预准备语句

名称参数比问号占位符更清晰、更明显。在本例中,我们谈论的是用户定义的占位符,可以根据以下架构命名:

:example

命名参数不应包含空格或连字符 (-)。相反,您应该使用下划线 (_)。

在下面的示例中,数据库操作 INSERT 显示为具有命名参数的预准备语句:

<?php
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root', '');

// prepare SQL statement
$statement = $pdo->prepare("INSERT INTO users (forename, surname, email, password) 
VALUES (:forename, :surname, :email, :password)");

// bind parameter
$statement ->bindParam(':forename', $forename);
$statement ->bindParam(':surname', $surname);
$statement ->bindParam(':email', $email);
$statement ->bindParam(':password', $password);

// insert data sets
$forename = "Anders";
$surname = "Andersen";
$email = "anders@andersen.com";
$password = "mnbvc";

if ($statement->execute())
  echo "New record $forename created successfully<br>";

$forename = "Matti";
$surname = "Meikäläinen";
$email = "matti@meikäläinen.com";
$password = "jhgfd";
$statement->execute();

// display status
if ($statement->execute())
  echo "New record $forename created successfully<br>";
?>

在准备好的语句中是命名参数:forename,:surname:email:p assword。然后,我们通过 bindParam() 将其绑定到变量 $forename$surname、$email  $password。在当前示例中,我们在示例表中命名了列的参数和变量。语法未指定此内容。因此,建议使用易于阅读的源代码意义上的标准化命名。变量值的赋值和 SQL 语句的执行类似于前面的示例。

MySQL 中的日期和时间函数

MySQL和MariaDB支持多种功能,能够处理日期和时间信息。可以在此处找到它们的完整列表。在这个面向初学者的 MySQL 教程中,我们将自己限制为一个选择。

日期和时间功能 描述
CURRENT_TIMESTAMP() / 现在() 通过 SQL 命令 UPDATE 的示例,我们已经熟悉了函数 NOW()。在这种情况下,我们只是在处理函数 CURRENT_TIMESTAMP() 的同义词。此函数始终在数据库操作的上下文中生效,该操作应遵循当前日期和时间
CURDATE() / CURRENT_DATE() CURDATE() 函数返回当前日期
CURTIME() / CURRENT_TIME() CURTIME() 函数返回当前时间
DAY() / DAYOFMONTH() 返回月份中的某一天 (0 – 31);需要日期或时间戳作为参数
星期() 返回星期几 (1 = 星期日);需要日期或时间戳作为参数
月() 返回月份 (1-12);需要日期或时间戳作为参数
年() 返回年份 (1000 – 9999, 0),需要日期或时间戳作为参数
日期() 从时间或日期信息中提取日期;需要日期或时间戳作为参数
时间() 从时间和日期信息中提取时间;需要日期或时间戳作为参数
DATE_FORMAT() 根据指定的参数格式化时间或细节;需要日期或时间戳作为参数

在MySQL中应用时间和日期函数的可能场景的一个示例是数据库查询,其中应读出在某一天创建的所有数据集。

以下脚本为我们提供了今天创建的示例表用户的所有数据集:

<?php
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root', '');
$sql = "SELECT forename, surname, email FROM users WHERE DATE(created_at) = CURDATE()";
foreach ($pdo->query($sql) as $row) {
   echo $row['forename'] . " " . $row['surname'] . "<br />";
   echo "E-Mail: " . $row['email'] . "<br /><br />";
}
?>

为了确保仅显示今天的条目,我们在 SQL 语句中使用以下条件:

DATE(created_at) = CURDATE()

接下来,在 DATE() 函数的帮助下,我们从保存在 created_at 列中的时间戳中提取日期,然后将其与当前日期同步。因此,SELECT 命令仅选择时间戳与当前日期对应的条目。

或者,我们也可以选择我们在 16.12.2016 更新的条目。为此,我们只需要调整 SQL 语句的条件:

SELECT forename, surname, email FROM users WHERE DATE(updated_at) = '2016-12-16'

在这种情况下,从时间戳中提取的日期信息与具体日期进行核对。此外,您可以将查询范围缩小到特定的年、月或日。

以下语句与 users 表中在 12 月创建的所有条目相关:

SELECT forename, surname, email FROM users WHERE month(created_at) = 12";

除了等号,SQL 在条件下还支持以下运算符:

运营商 描述
= 相等
小于
<= 小于或等于
>= 大于或等于
!= 不等

此外,您还可以使用逻辑符号链接多个条件:

逻辑运算符 描述
或即 || 逻辑或
和,即 && 逻辑和

例如,以下语句选择在 2 月之后和 4 月之前创建的所有条目:

SELECT forename, surname, email FROM users WHERE MONTH(created_at) > 2 AND MONTH(created_at) < 4";

到目前为止,我们已经以预定格式将日期和时间详细信息保存在数据库中。但是,对于MySQL和MariaDB,它们不一定设置为此。DATE_FORMAT() 函数为您提供可选参数,允许您根据需要格式化日期和时间。

<?php
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root', '');
$sql = "SELECT forename, surname, DATE_FORMAT(created_at,'%D %M %Y') AS created_at FROM users WHERE id=1";
  foreach ($pdo->query($sql) as $row) {
  echo $row['forename'] . " " . $row['surname'] . " your profile was created at: " . $row['created_at'] . ".<br /><br />";
}
?>

下表显示了根据 MySQL 文档的 DATE_FORMAT() 函数的可能参数。

参数 描述 值范围/示例
%c 1 位或 2 位数字的月份 0 到 12
%d 带 2 位数字的月份中的某天 00 到 31
%e 带有 1 位或 2 位数字的月份中的某天 0 到 31
%H 2 位数字的小时数 00 到 23
%i 2 位数字的分钟数 00 到 59
%j 一年中 3 位数字的天数 001 到 366
%k 1 位或 2 位数字的小时数 0 到 23
%M 以当前区域设置写入的月份 1月、2月、3月等
%m 月份 2 位数字 00 到 12
%s 2 位数字的秒数 00 到 59
%T 24 小时格式的时间(简称“%H:%i:%S”) 呵呵:毫米:不锈钢
%u 一年中的周数,从星期一开始 00 到 53
%W 当前区域设置中的星期几 周一、周二等
%w 以数字表示的星期几 0 = 星期日,6 = 星期六
%Y 年份(4 位数字) 例如 2016 年
%y 年份(2 位数字) 例如 16 年

MySQL 错误消息

如果碰巧脚本未按预期执行,这通常是由于源代码中的语法错误或错误命名的表、列和/或变量造成的。在这种情况下,它不一定会导致错误消息。通常,所需的结果保持不变,没有任何失败操作的迹象。

使用 errorInfo(),您有一个函数,允许您访问与最新数据库操作相关的高级错误信息 — 例如,通过 Web 浏览器发出这些信息。

以下用于更新电子邮件地址的脚本将 errorInfo() 函数与 if 循环结合使用。为此,需要正确执行 SQL 语句。如果执行此操作没有错误,则 Web 服务器将返回字符串“更新成功”。否则,它将在指定的代码下执行。

在当前示例中,我们通知用户发生了 SQL 错误的事实,从而通过 errorInfo() 发出受影响的 SQL 语句以及高级错误信息:

<?php
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root', '');
$statement = $pdo -> prepare("UPDATE user SET password = :password, updated_at = NOW() WHERE id = 1");
$statement ->bindParam(':password', $password);
$password = "YXDli_89%s";
if ($statement ->execute()){
   echo "Update successful";
} else {
   echo "SQL Error <br />";
   echo $statement->queryString."<br />";
   echo $statement->errorInfo()[2];
}
?>

如果我们通过 Web 服务器执行脚本,则会显示以下信息:

SQL Error 
UPDATE user SET password = :password, updated_at = NOW() WHERE id = 1
Table 'test.user' doesn't exist

SQL 命令 UPDATE 引用名称为 user 的表但是,我们给表命名为用户。SQL 服务器找不到请求的表,因此显示消息“test.user”不存在。在这种情况下,错误的原因仅仅是可以快速纠正的键入错误。

使用 errorInfo() 函数的返回值,我们正在处理一个包含三个元素的数组:

[0] = SQL 错误代码

[1] = 特定于驱动程序的错误代码

[2] = 特定于驱动程序的错误消息

通过 errorInfo() 检索的确切信息可以通过在方括号中概述所需的元素来指定。

通常情况下,详细的错误信息很少仅通过 Web 浏览器发布。有了这些信息,用户通常只能做很少的事情。而潜在的攻击者使用错误消息来帮助他们了解SQL查询,并通过它检测应用程序的弱点。因此,强烈建议向用户提供的有关错误的信息保持非常笼统,并在内部存储更具体的错误信息。如何执行此操作的示例如下:

<?php
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root', '');
$statement = $pdo->prepare("UPDATE user SET password = :password, updated_at = NOW() WHERE id = 1");
$statement->bindParam(':password', $password);
$password = "YXDli_89%s";
if ($statement->execute()) {
   echo "Update successful";
} else {
  echo “Unfortunately an error has occurred during the updating of your password. Please contact our administrator on: admin@website.com.”;
  $error = DATE("Y-m-d H:i:s") . " - " . __FILE__ . " - " . $statement->queryString . " - " . $statement->errorInfo()[2] . " \r\n";
  file_put_contents("sqlerrors.log", $error, FILE_APPEND); 
}
?>

我们不是函数 errorInfo() 在 Web 浏览器中通过 echo 返回值,而是将其与当前时间戳、文件路径和受影响的 SQL 语句一起保存在 $error 变量中。

PHP 函数 DATE() 以指定的格式发布 Unix 时间戳。所谓的常量__FILE__为我们提供了 test.php 文件的完整路径。我们检索当前的 SQL 语句,就像我们在前面的示例中通过 $statement->queryString 所做的那样。在此之后,存储在$error中的文件将作为文本存储在 htdocs 文件夹中的 sqlerrors.log 文件中。这是在函数 file_put_contents() 的帮助下完成的。

加入

如前面关系数据库一章所述,可以同时从多个表中查询数据。现在您已经熟悉了基本的数据库操作,我们将进一步解决这个问题,并向您展示如何在联接中链接数据库中的不同表。

查询上下文中的表合并是在 SQL 命令 JOIN 的帮助下进行的。这样,两个或多个规范化表通过公共列链接。这是通过外键实现的。

以下示例演示了数据库表的这种链接:

此表显示了 1960 年代我们最喜欢的歌曲,并作为低质量数据库设计的示例。

该表包含冗余数据字段。作为规范化过程的一部分,我们通过拆分文件来删除这些文件,然后在外键的帮助下链接它们。

普通形式

良好的数据库设计可以以最低级别的冗余为特征。通过规范化数据表可以避免重复条目。在关系数据库模型领域,已经建立了三种连续的范式,每种形式都建立在另一种形式之上。这些为最佳数据结构指定了设置规则。

第一范式

如果表的所有属性值都是原子的,则该表属于第一个范式。如果属性值仅包含一条信息,则将其视为原子值。这在我们上面的坏例子中得到了明确的证明。

例如,查看表相册中的列album_title艺术家。我们没有在单独的表格中列出表格中的每条信息,而是决定通过简单地将有关专辑发行年份以及乐队存在多长时间的信息放在专辑标题后面的括号中,从而使自己更轻松。所有这些信息都放在艺术家的表格标题下。但是,如果我们希望检索某一年发布的所有标题,那么有一天我们可能会对这种草率感到遗憾。

因此,我们建议改为基于第一个范式的规则创建表。考虑到这一点,我们的示例表应如下所示:

所有数据现在都是独立的,更具可读性。但是,我们的表仍然包含一些冗余。在接下来的几个步骤中,我们将解释如何摆脱这些。

第二范式

如果满足第一范式的所有条件,并且每个非键属性在功能上完全依赖于表的总体主键,则可以说表属于第二范式。

数据表通常只包含一列,然后用作主键。像这样的表将自动属于第二范式,如果它们恰好符合第一范式的所有标准。有时也会发生表的主键由两列组成的情况。我们的示例表就是这种情况。

要从标题列中检索所需的标题,我们需要曲目列中的album_id和突出显示的曲目编号。例如,可以通过主键 album_ID = 3 和 track = 1 检索曲目“对魔鬼的同情”。在本例中,我们正在处理复合主键,这是专门用于查询所必需的,这些查询会引用标题列。 album_title、发行、艺术家years_active栏完全取决于album_id。因此,这些列没有完全独立于整个主键的功能。第二范式的条件尚未满足。

我们可以通过将标题列转移到新表,然后通过外键 (album_id) 将其与输出表链接来更改这一点:

修改后的表相册仅包含一个部分主键,并自动满足第二范式的条件。新表标题仅包含非键列标题。这在功能上完全依赖于主键的两个部分(album_id轨道),因此属于第二范式。

但是,即使在第二范式中,我们的数据表相册也包含冗余的条目。

第三范式

如果表符合第三范式的标准,那么第二范式的所有条件(因此也是第一范式=)都需要满足。此外,任何非键属性都不能依赖于键属性的不可传递。虽然这个条件听起来很复杂,但可以很容易地解释:当一个非键属性依赖于另一个非键属性时,总是会发生传递依赖

这与包含列艺术家years_active的示例表相册非常相关。虽然可以通过album_id识别艺术家,但另一方面,乐队存在的年份和时期取决于艺术家,也取决于album_id。这样做的一个缺点是,每次输入来自已列出的艺术家之一的新专辑时,数据库管理系统都会自动在years_active列中保存一个冗余值。

为了满足第三范式的标准,并随之删除表中的所有冗余,我们首先需要将艺术家列(包括 years_active)转移到一个单独的表,并通过外键将其链接到输出表专辑

然后我们剩下三个规范化的表:艺术家、专辑标题。

如果我们现在希望在数据库中输出一个特定的标题,包括专辑和艺术家的信息,我们应该在 SQL 命令和相应的外键的帮助下链接三个单独的表。

通过 phpMyAdmin 定义外键

如果您选择了InnoDB作为数据库引擎,则可以通过管理软件phpMyAdmin的图形用户界面定义外键关系。在这种情况下,表的主键可以作为外键部署在任意数量的表中。

就我们的示例而言,我们需要两个连接才能链接三个规范化表专辑、艺术家标题。

  • 对于第一个连接,我们使用专辑表中的主键album_id作为表轨道中的外键。
  • 对于第二个连接,我们使用艺术家表中的主键artist_id作为表专辑中的外键。

下图概述了各种外键关系:

链接数据表时,请务必记住,需要为应该用作外键的列提供属性 UNIQUE 或 INDEX。

主键和外键之间的关系通常属于关系类型 1:n。表 A 主列中的每个数据字段都与表 B 的外键列中的任意数量的 (n) 个数据字段相关。但是表 B 的外键列中的每个数据字段都恰好引用表 A 的主键列中的一个数据字段。例如,如果我们在主列album_id相册中有四个条目。然后,通过外键title.album_id将它们与表标题中的八个条目链接。

为了建立所需的连接,我们首先在phpMyAdmin中设置表相册艺术家标题,并在表创建的上下文中指定我们的主键,正如通过“索引”选项已经概述的那样。您还应该注意,以后应用作外键的列也通过 index 选项标记为 INDEX 或 UNIQUE。但是,只有 INDEX 适用于 1:n 关系,因为最终不允许 UNIQUE 字段中的值重复。

下一步将看到我们定义外键。我们使用专辑表的示例来演示这一点。然后,我们在导航面板中选择表格,并在菜单列表中找到“结构”选项卡。在这里,您将找到“关系视图”选项:

外键关系可以通过“外键约束”选项在数据表的关系视图中定义:

interpret_id列应充当专辑表中的外键,该外键基于解释表中的interpret_id主键。

在下拉菜单中的“列”下,我们选择interpret_id作为外键。请注意,此处仅列出标记为“索引”、“唯一”“主要”的列。在由三部分组成的条目字段“外键约束(InnoDB)”中,我们确定外键应基于哪个主键、哪个表以及哪个数据库。我们的选择如下:

数据库:测试

表:艺术家

主键:artist_id

“约束名称”可以保持为空,因为数据库管理系统将在此处自动分配一个名称。但是,一旦更改或删除了外键的基础主键,就必须指定表如何充当外键。

例如,如果删除了父表艺术家中的艺术家,则与此条目关联的主键也会被删除。因此,有必要通过外键澄清与此条目相关的条目应该发生什么情况 - 在我们的示例中,这将是艺术家的专辑。

要确定在UPDATE或删除的情况下具有外键的表的反应,您可以在MySQL中选择四个选项即MariaDB。

  • 限制:RESTRICT 选项排除对父表的任何更改,只要存在引用父表的其他表。在我们的例子中,如果专辑表中的数据集与艺术家表中的数据集链接,则无法删除它们
  • 级 联:CASCADE 选项可确保父表中的任何更改都传递到引用回父表的所有其他表。例如,如果我们要将滚石乐队的artist_id从 2 更改为 8,则此更改也将注册到所有其他使用 artist_id 作为外键的表中。这是通过使用外键选项 CASCADE 完成的。如果删除了父表中的条目,则还将确保其他表中与此条目相关的所有数据集也被删除。但是:请记住,这也意味着删除单个条目会导致许多数据集消失。
  • 设置空值:选择 SET NULL 选项会导致在更改或删除父表的主键后立即将外键列的值设置为 NULL
  • 无操作:对于 MySQl,NO ACTION 选项等同于 RESTRICT 选项。

为外键关系指定所需选项后,单击“保存”确认输入。然后,数据库管理系统将自动为新定义的关系分配一个名称。

MySQL 和 MariaDB 中的 JOIN 类型

外键关系使您可以同时从不同的表中检索数据,所有这些数据都只需一个 SQL 语句。为此,MySQL和MariaDB中提供了四种类型的JOIN:

  • 内部连接:使用内部连接,数据库管理系统在通过 JOIN 绑定的两个表中搜索公共条目。唯一要扫描的数据集是那些存在匹配的数据集,即两个表中的链接列(主键和外键)中的值对应。
  • 外部联接:使用外联接可以区分左数据库和右数据库。它与 INNER JOIN 的不同之处在于,扫描的不仅仅是包含两个表中匹配项的数据集。还会扫描右侧或左侧表的所有其他数据集。
  • 左连接:扫描左表中的所有数据集以及右表中找到匹配项的所有数据集。
  • 右联接:将扫描右表中的所有数据集以及左表中找到匹配项的所有数据集。

为了简洁起见,我们的 MySQL 初学者教程,我们将自己限制在内部连接。

内部联接的语法类似于以下基本架构:

SELECT * FROM table1
INNER JOIN table2 ON table1.foreignkey = table2.primarykey
WHERE column = value

SQL 命令 SELECT 与占位符 * 结合使用,指示数据库管理系统从 ON- 和 WHERE- 子句的条件有效的所有列中选择值。

当我们处理内部连接时,只有表1的外键和表2的主键之间存在匹配的数据集才会从数据库中检索。此外,借助 WHERE 子句,您可以定义可选的过滤器函数。

使用我们的规范化表专辑、艺术家和曲目的示例可以清楚地说明这一点

<?php
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root', '');
$sql = "SELECT * FROM album
INNER JOIN interpret ON album.interpret_id = interpret.interpret_id";
foreach ($pdo->query($sql) as $row) {
   echo $row['album_title'] . " was released by " . $row['interpret'] . " in " . $row['released'] . ".<br /><br />";
}
?>

示例脚本显示了一个 INNER JOIN,其中表相册与表艺术家链接。 我们只选择主键和外键之间匹配的数据集。

album.interpret_id = interpret.interpret_id

在我们的数据库中,所有数据集都是这种情况(因此,接或右联接会产生相同的结果)。在此之后,我们在 foreach 循环和语言结构 echo 的帮助下在浏览器中显示扫描的值

然后,我们扫描了艺术家表中的详细信息,以及有关专辑标题和唱片发行年份的详细信息。

显示哪些连接的数据集受 WHERE 子句条件的限制。例如,如果我们希望输出 1968 年发行的专辑,我们可以输入以下内容:

<?php
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root', '');
$sql = "SELECT * FROM album
INNER JOIN interpret ON album.interpret_id = interpret.interpret_id WHERE released = 1968";
foreach ($pdo->query($sql) as $row) {
   echo $row['album_title'] . " was released by " . $row['interpret'] . " in " . $row['released'] . ".<br /><br />";
}
?>

通过使用 WHERE release = 1968,我们将浏览器中的输出限制为一个专辑。滚石乐队的乞丐宴会现在是我们可管理数据库中唯一一张于 1968 年发行的专辑。

JOIN 命令允许您在数据网络中将任意数量的表组合在一起。在下面的示例中,我们将专辑表与 INNER JOIN 中的艺术家曲目表链接。这意味着我们可以输出与存储在数据库中的曲目相关的所有信息。

<?php
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root', '');
$sql = "SELECT * FROM album
INNER JOIN interpret ON album.interpret_id = interpret.interpret_id 
INNER JOIN title ON album.album_id = title.album_id";
foreach ($pdo->query($sql) as $row) {
   echo $row['title'] . " was released by " . $row['interpret'] . " as Track " . $row['track'] . " on " . $row['album_title'] . " in " . $row['released'] . ".<br /><br />";
}
?>

即使在这里,如果需要,我们也可以使用过滤器函数定义一个 WHERE 子句。例如,如果我们希望只显示专辑“Abbey Road”的曲目 7 上的信息。

<?php
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root', '');
$sql = "SELECT * FROM album
INNER JOIN interpret ON album.interpret_id = interpret.interpret_id 
INNER JOIN title ON album.album_id = title.album_id WHERE track = 7 AND album_title = 'Abbey Road'";
foreach ($pdo->query($sql) as $row) {
   echo $row['title'] . " was released by " . $row['interpret'] . " as Track " . $row['track'] . " on " . $row['album_title'] . " in " . $row['released'] . ".<br /><br />";
}
?>

确保当涉及到曲目标题时,我们正在处理多部分主键。如果我们希望参考特定标题,那么除了曲目编号外,我们还需要album_id,该与专辑标题一起在专辑表中突出显示。

从初学者到专业

我们针对初学者的MySQL教程可以被视为一个速成课程,旨在让您更熟悉基于SQL的数据库系统的基础知识,并演示简单实用的数据库操作示例。如果您对软件可能性的兴趣超出了此处描述的范围,我们建议您在上面的介绍性章节中链接的DBMS MySQL和MariaDB的文献。除此之外,还有无数的网站提供最流行的数据库管理系统的教程和使用示例。

还推荐互联网平台Stack Overflow。在这里,超过6万开发人员的用户社区就当前的问题和软件开发问题提出了问题并交换了建议。当然,在IONOS数字指南中,有许多关于数据库主题的广泛文章。这些可以使用下面列出的标签找到。






添加微信号

13805327355

点击拨打电话咨询