MySQL 函数:字符串、数字、用户定义、存储

⚡ 智能摘要

MySQL 函数在存储或检索数据之前对其进行转换,并返回单个计算结果。本文首先介绍内置的字符串、数值和日期函数,然后展示存储函数和用户自定义函数如何扩展数据库引擎本身的功能。

  • 🔤 字符串函数: UCASE、LCASE 和 CONCAT 在查询时重塑文本;使用 AS 为计算列创建别名,以便结果集带有可读的标题。
  • 🔢 数字 Opera目的: DIV 执行整数除法,/ 返回十进制商,%(或 MOD)返回除法的余数。
  • 📅 日期函数: DATE_FORMAT 将存储的 YYYY-MM-DD 值转换为任何显示模式,例如 %d-%m-%Y,而无需更改任何一行应用程序代码。
  • 🛠️ 存储函数: CREATE FUNCTION 在服务器内部注册可重用的逻辑;当主体调用 CURDATE() 或 NOW() 时,声明它不具有确定性。
  • ⚙️ 用户自定义函数: 用 C 语言编写的外部例程 C++ 编译到服务器端后,它们的行为与原生函数完全相同。
  • 🚀 性能影响: 将计算结果推送到数据库中,可以消除每个客户端应用程序中的重复逻辑,并减少网络往返次数。

是什么 MySQL 功能?

MySQL 不仅可以存储和检索数据。 它也可以 对数据进行操作 在检索或保存之前。那就是 MySQL 函数就派上用场了。函数其实就是一段代码,它执行一个操作并返回结果。有些函数接受参数,而有些函数则不接受参数。

我们来看一个例子。默认情况下, MySQL 以“YYYY-MM-DD”格式保存日期数据类型。假设我们开发了一个应用程序,用户希望以“DD-MM-YYYY”格式返回日期。我们可以使用 MySQL 可以使用内置函数 DATE_FORMAT 来实现这一点。DATE_FORMAT 是 Python 中最常用的函数之一。 MySQL我们将在本课后面详细探讨这个问题。

无论其类型如何,一个函数 始终返回单个值, 可以接受零个或多个参数 括号内的内容,以及 可以在任何允许使用表达式的地方使用。 — 在 SELECT 列表、WHERE 子句或 ORDER BY 子句中。

为何使用 MySQL 功能?

既然我们已经了解了什么是函数,那么下一个问题是,我们为什么要将这项工作推送到数据库中。

为什么使用 MySQL 功能

如上图所示,一个函数接受一个输入值,在数据库引擎内部应用一次逻辑,并将一个结果返回给每个请求该结果的应用程序。

程序员可能会想:“何必呢?” MySQL 函数?同样的效果也可以用脚本语言或编程语言实现。”的确,我们可以通过在应用程序中编写过程来实现这一点。

回到我们的 DATE 示例,为了让用户获得所需格式的数据,业务层必须自行进行必要的处理。

当应用程序必须与其他系统集成时,这就会成为一个问题。当我们使用 MySQL 诸如DATE_FORMAT之类的函数,其功能已嵌入数据库中,任何需要数据的应用程序都能以所需的格式获取数据。 减少业务逻辑中的重复工作,并减少数据不一致。.

另一个需要考虑的原因 MySQL 它们的功能在于可以帮助减少客户端/服务器应用程序中的网络流量。业务层只需调用已存储的函数,无需通过网络拉取原始数据行进行操作。平均而言,使用函数可以显著提升系统整体性能。

有哪些 MySQL 功能

既然“是什么”和“为什么”的问题都已明确,我们现在可以来看一下这三类功能。 MySQL 提供:内置函数、存储函数和用户自定义函数。

内建功能

MySQL 它捆绑了许多内置函数——这些函数已经在……中实现。 MySQL 服务器。它们允许我们对数据执行多种类型的操作,并可分为以下几个常用类别。

  • 字符串函数 – 对字符串数据类型进行操作
  • 数值函数 – 对数字数据类型进行操作
  • 日期功能 – 对日期数据类型进行操作
  • 汇总功能 – 对所有上述数据类型进行操作并生成汇总结果集。
  • 其他功能 – MySQL 它还支持其他类型的内置函数,但本课程仅限于上述组。

现在让我们详细了解一下上面提到的每个分组。我们将使用“Myflixdb”示例数据库来解释最常用的功能。

字符串函数

字符串函数操作的是文本值。在我们的电影表中,标题以大小写混合的方式存储。假设我们想要查询返回全部大写的标题。“UCASE”函数接受一个字符串作为参数,并将每个字母转换为大写,如下面的脚本所示。

SELECT `movie_id`, `title`, UCASE(`title`) AS `upper_case_title` FROM `movies`;

点击这里

  • UCASE(`title`) 这是一个内置函数,它接受标题作为参数,并以大写字母返回标题。
  • AS `upper_case_title` 为计算列添加别名,以便结果集包含可读的标题而不是原始表达式。

在以下位置执行上述脚本 MySQL 使用 Workbench 对 Myflixdb 进行测试,得到的结果如下所示。

电影 ID 标题 upper_case_title
16 67% 有罪 67%的人有罪
6 天使与魔鬼 天使与魔鬼
4 Code 黑 代号“黑衣”
5 爸爸的小女孩 爸爸的小女儿们
7 达芬奇 Code 达芬奇密码
2 忘掉莎拉·马歇尔 忘掉莎拉·马歇尔
9 Honey moonERS 蜜糖 MOONERS
19 电影3 电影 3
1 加勒比海盗4 加勒比海盗4
18 样片 样片
17 大独裁者 大独裁者
3 X-战警 X-MEN

除了 UCASE 之外,还有两位伙伴值得我们铭记: LCASE 将字符串转换为小写,并且 康卡特 将两个或多个字符串合并成一个字符串。完整列表请参见…… MySQL 字符串函数引用.

数值函数

如前所述,数值函数作用于数值数据类型。我们也可以直接在 SQL 语句中对数值数据执行数学计算。

算术运算符

MySQL 支持以下算术运算符,可用于在 SQL 语句中执行计算。

姓名 描述
DIV 整数除法
/ 分部
小组tracTION
+ 增加
* 乘法
% 或 MOD 系数

以下是每个运算符的示例。

整数除法 (DIV) — DIV 函数会舍弃小数部分,只返回整数部分。

SELECT 23 DIV 6;

执行上述脚本后,我们会得到以下结果。 3.

除法运算符 (/) — 与 DIV 运算符不同,除法运算符会保留结果的小数部分。

SELECT 23 / 6;

执行上述脚本后,我们会得到以下结果。 3.8333.

小组trac运算符(-)

SELECT 23 - 6;

执行上述脚本后,我们会得到以下结果。 17.

加法运算符 (+)

SELECT 23 + 6;

执行上述脚本后,我们会得到以下结果。 29.

乘法运算符 (*)

SELECT 23 * 6 AS `multiplication_result`;

结果:

乘法结果
138

取模运算符(% 或 MOD)

取模运算符将 N 除以 M,得到余数。让我们来看一个取模运算符的例子,使用与前面例子相同的值。

SELECT 23 % 6;
-- OR, equivalently:
SELECT 23 MOD 6;

执行任一脚本都会给我们带来以下结果 5.

现在让我们看看 MySQL.

FLOOR 此函数会移除数字的小数位,并将其向下取整到最接近的整数。以下脚本演示了它的用法。

SELECT FLOOR(23 / 6) AS `floor_result`;

结果:

地板结果
3

圆型行李箱 此函数将数字四舍五入到最接近的整数。因为 23 / 6 的计算结果为 3.8333,所以 ROUND 返回 4,而 FLOOR 返回 3——两者不能互换使用。

SELECT ROUND(23 / 6) AS `round_result`;

结果:

轮次结果
4

兰德 此函数生成一个随机数。每次调用该函数时,其值都会改变。以下脚本演示了它的用法。

SELECT RAND() AS `random_result`;

日期功能

日期函数可处理日期和日期时间数据类型。DATE_FORMAT 函数解决了引言中提到的“YYYY-MM-DD 与 DD-MM-YYYY”格式的问题。

日期格式 该脚本接受两个参数:要格式化的日期值,以及由占位符构成的格式字符串。以下脚本会以用户要求的“日-月-年”格式返回每个发布日期。

SELECT `title`, DATE_FORMAT(`date_released`, '%d-%m-%Y') AS `formatted_date`
FROM `movies`;

下面列出了最常用的格式占位符。

占位符 输出示例
%d 月份中的日期,两位数 04
%m 月份,两位数 08
%Y 年份,四位数 2012
%M 月份全称 八月
%他的 Hours分钟,秒 14:35:09

日常工作中还会经常用到其他三个日期函数:

  • 更新() 返回当前日期,格式为 YYYY-MM-DD。
  • 现在() 返回当前日期 时间。
  • DATEDIFF(d1, d2) 返回两个日期之间的天数——这是任何逾期租金报告的基础。

完整列表请参见: MySQL 日期和时间函数参考.

存储函数

内置函数可以满足常见需求。当业务规则更加具体时,我们需要编写自定义函数——这就是存储函数的作用。

存储函数与内置函数的行为方式完全相同,区别在于它们需要由您自行定义。创建后,存储函数可以像其他任何函数一样在 SQL 语句中使用。基本语法如下所示。

CREATE FUNCTION sf_name ([parameter(s)])
RETURNS data_type
[DETERMINISTIC | NOT DETERMINISTIC]
BEGIN
    -- procedural statements
END

点击这里

  • “CREATE FUNCTION sf_name ([parameter(s)])” 是强制性的,并说明 MySQL 服务器创建一个名为 `sf_name` 的函数,括号内定义了可选参数。
  • “返回数据类型” 是必填项,用于指定函数返回的数据类型。
  • **确定性** 声明无论提供相同的参数,该函数都返回相同的值。 “非决定论的” 表达了相反的观点。
  • “开始……结束” 封装函数执行的过程代码。

假设我们想知道哪些租借的电影已经过了归还日期。我们可以创建一个存储函数,该函数接受归还日期作为参数,并将其与服务器上的当前日期进行比较。如果当前日期晚于归还日期,则表示电影已逾期,我们返回“是”;否则,我们返回“否”。

DELIMITER |
CREATE FUNCTION sf_past_movie_return_date (return_date DATE)
RETURNS VARCHAR(3)
NOT DETERMINISTIC
BEGIN
    DECLARE sf_value VARCHAR(3);
    IF CURDATE() > return_date THEN
        SET sf_value = 'Yes';
    ELSEIF CURDATE() <= return_date THEN
        SET sf_value = 'No';
    END IF;
    RETURN sf_value;
END|
DELIMITER ;

⚠️警告——不要将此函数标记为DETERMINISTIC。 函数体调用了 CURDATE() 函数,因此同一个参数今天可能返回“否”,明天可能返回“是”。将时间相关的函数声明为 DETERMINISTIC 会误导优化器,并且对于基于语句的复制是不安全的。 不确定 每当主体调用 CURDATE()、NOW() 或 RAND() 时。

执行上述脚本会创建存储函数 `sf_past_movie_return_date`。现在让我们来测试一下。

SELECT `movie_id`, `membership_number`, `return_date`, CURDATE(),
       sf_past_movie_return_date(`return_date`) AS `is_overdue`
FROM `movierentals`;

在以下位置执行上述脚本 MySQL 使用 Workbench 对 myflixdb 数据库进行测试,得到以下结果。

电影 ID 会员号码 归期 更新() 已逾期
1 1 04-08-2012
2 1 25-06-2012 04-08-2012
2 3 25-06-2012 04-08-2012
2 2 25-06-2012 04-08-2012
3 3 04-08-2012

注意这两行 NULL 值。当 `return_date` 为 NULL 时,两个比较的结果都为 NULL 而不是 TRUE 或 FALSE,因此两个 IF 分支都不会执行,函数返回 NULL——这是预期结果,因为未归还的电影没有归还日期可供比较。

用户定义函数

当仅使用 SQL 速度不够快时, MySQL 还有第三种选择。用户自定义函数 (UDF) 是用编译型语言编写的,例如: C or C++用户自定义函数 (UDF) 被构建到共享库中,并注册到服务器。添加后,它们的调用方式与其他函数相同。由于 UDF 作为本地代码在服务器进程中运行,因此它适合处理繁重的计算任务——但 UDF 中的一个错误可能会导致服务器崩溃,所以 UDF 的使用频率远低于存储函数。

内置函数、存储函数和用户自定义函数:你应该使用哪一个?

这三个函数族都返回同一个值,并且可以从任何 SQL 语句中调用,但它们的区别在于编写者、运行环境以及风险程度。下表总结了这些区别。

标准 内建功能 存储函数 用户自定义函数(UDF)
谁写的 附带 MySQL 你,在 SQL 中 你,在 C 或 C++
居住地 服务器内部 在数据库中,使用 CREATE FUNCTION 创建 服务器加载的已编译共享库
典型用途 格式化、数学运算、聚合 可重用的业务规则,例如逾期支票 SQL 无法表达 CPU 密集型或专门的逻辑
主要风险 没有 如果逐行调用大表,速度会很慢。 库中的崩溃可能会导致服务器宕机。

一般来说,先尝试使用内置函数。如果没有合适的内置函数,则编写一个存储函数,以便将规则集中在一处。只有当存储函数的运行速度明显过慢时,才考虑使用用户自定义函数 (UDF)。

常见问题

函数必须返回一个且仅返回一个值,并且可以在 SELECT、WHERE 或 ORDER BY 表达式中使用。存储过程可以返回零个或多个结果集,不能嵌入表达式中,并且使用 CALL 语句调用。

运行 DROP FUNCTION IF EXISTS sf_name; 然后重新创建它。 MySQL 没有 CREATE OR REPLACE FUNCTION,ALTER FUNCTION 只能更改注释或安全类型等特征,而不能更改正文。

可以。在 WHERE 子句中,围绕索引列包装的函数可以防止这种情况发生。 MySQL 避免使用该索引,强制执行全表扫描。对原始列进行筛选,并仅在 SELECT 列表中应用该函数。

是的。AI 助手可以根据简单的英文规则生成 CREATE FUNCTION 代码。在生产服务器上运行之前,务必检查生成的函数体是否具有正确的 DETERMINISTIC 特性、NULL 值处理方式以及参数数据类型。

不。人工智能模型可能会随意创建函数名称、忽略空值情况或忽略版本差异。请在数据副本上测试每个生成的函数,并将结果与​​您自己编写并验证过的查询进行比对。

总结一下这篇文章: