SQL 更多知识:使用函数 FUNCTION

在实际的数据库开发中,面对重复的复杂计算(如多字段拼接、个性化数据校验、自定义统计逻辑),编写自定义函数能大幅提升代码复用性和开发效率。本章将从函数的基础概念出发,带你全面掌握 SQL 函数的定义、使用场景、执行方式和创建方法。

 

什么是 SQL 函数

SQL 函数是一组预先定义(或自定义)的、可重复执行的代码块,它接收输入参数(可选),经过特定逻辑处理后返回一个或多个结果。你可以把它理解为一个 “数据处理工厂”:输入原材料(参数),经过工厂加工(函数逻辑),最终产出成品(返回值)。

从类型上看,SQL 函数主要分为两类:

  • 内置函数:数据库系统自带的函数,无需创建即可直接使用,比如计算字符串长度的LENGTH()、求平均值的AVG()、日期转换的DATE_FORMAT()等。

  • 自定义函数:由开发者根据业务需求自行编写的函数,用于实现内置函数无法满足的个性化逻辑。

举个例子:使用内置函数UPPER()将字符串转为大写

-- 执行内置函数,将"sql function"转为大写
> SELECT UPPER('sql function')

UPPER('sql function')|
---------------------+
SQL FUNCTION         |

1 row(s) fetched.

 

为什么要使用函数

在日常 SQL 开发中,函数的价值主要体现在以下 4 个方面:

(1)简化重复逻辑,提升代码复用性:如果你的业务中需要频繁执行某个计算(比如计算商品折扣价、用户年龄),无需每次都写重复的计算公式,只需将逻辑封装成函数,调用即可。例如:

-- 不使用函数:每次计算折扣价都要写重复逻辑
SELECT product_name, price * 0.8 AS discount_price FROM products;

-- 使用函数:一次定义,多次调用,get_discount_price 是一个自定义的函数
SELECT product_name, get_discount_price(price) FROM products;

(2)降低代码复杂度,提升可读性:复杂的业务逻辑(比如多条件判断、嵌套计算)直接写在 SQL 语句中会让代码冗长且难以理解,封装成函数后,只需通过函数名即可清晰表达意图。

(3)统一数据处理规则,减少错误:通过函数固化数据处理逻辑(比如统一的日期格式转换、手机号脱敏规则),可以避免不同开发者编写不同逻辑导致的数据不一致问题。

(4)提升执行效率:数据库对函数有专门的优化机制,尤其是自定义函数,合理编写的函数能减少重复的查询和计算,降低数据库的执行压力。

 

执行函数

执行(调用)SQL 函数是最基础的操作,不同类型的函数调用方式略有差异,但核心逻辑一致。

执行内置函数

内置函数可直接在SELECT、WHERE、ORDER BY等子句中调用,语法为:函数名(参数1, 参数2, ...)。

常用内置函数示例:

-- 1. 字符串函数:拼接字符串
> SELECT CONCAT('Hello', ' ', 'SQL') AS result

result   |
---------+
Hello SQL|

1 row(s) fetched.

-- 2. 数值函数:求绝对值
> SELECT ABS(-100) AS result

result|
------+
   100|

1 row(s) fetched.

-- 3. 日期函数:获取当前日期
> SELECT CURDATE() AS result

result    |
----------+
2026-01-08|

1 row(s) fetched.

-- 4. 聚合函数:计算订单总金额
> SELECT SUM(total_amount) AS total_amount FROM `order`

total_amount|
------------+
   110379.00|

1 row(s) fetched.

执行自定义函数

自定义函数创建完成后,调用方式与内置函数一致,只需确保函数名和参数匹配:

-- 调用自定义函数 get_user_age
SELECT username, get_user_age(birthday) AS age FROM users;

注意,自定义 get_user_age 函数将在后续给出。

 

创建函数

当内置函数无法满足业务需求时,你可以创建自定义函数(UDF,User-Defined Function)。不同数据库(MySQL、Oracle、SQL Server)的函数创建语法略有差异,本文以 MySQL 为例讲解。

基本语法

下面是创建函数的语法:

CREATE FUNCTION 函数名(参数名1 数据类型, 参数名2 数据类型, ...)
RETURNS 返回值数据类型
[DETERMINISTIC] -- 可选:表示函数返回结果固定(相同输入必返回相同输出)
BEGIN
    -- 函数体:核心逻辑(变量定义、条件判断、计算等)
    RETURN 返回值;
END;

实战示例

示例1:创建计算用户年龄的函数

-- 创建函数 get_user_age
> CREATE FUNCTION get_user_age(birthday DATE)
RETURNS INT
DETERMINISTIC
BEGIN
    -- 定义变量存储年龄
    DECLARE user_age INT;
    -- 计算年龄:当前年份 - 生日年份,若未到生日则减1
    SET user_age = YEAR(CURDATE()) - YEAR(birthday);
    IF MONTH(CURDATE()) < MONTH(birthday) OR 
       (MONTH(CURDATE()) = MONTH(birthday) AND DAY(CURDATE()) < DAY(birthday)) THEN
        SET user_age = user_age - 1;
    END IF;
    -- 返回计算结果
    RETURN user_age;
END 

0 row(s) modified.

-- 调用函数
> SELECT get_user_age('2020-10-02') AS age

age|
---+
  5|

1 row(s) fetched.

示例 2:创建计算商品折扣价的函数,计算折扣后价格(保留 2 位小数)。

-- 创建折扣计算函数
> CREATE FUNCTION get_discount_price(original_price DECIMAL(10,2), discount_rate DECIMAL(3,2))
RETURNS DECIMAL(10,2)
DETERMINISTIC
BEGIN
    -- 处理异常:折扣率不能小于0或大于1
    IF discount_rate < 0 OR discount_rate > 1 THEN
        SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '折扣率必须在0-1之间';
    END IF;
    -- 计算折扣价并返回
    RETURN ROUND(original_price * discount_rate, 2);
END 

0 row(s) modified.

-- 调用函数
> SELECT get_discount_price(1278.45, 0.8) AS discount_price

discount_price|
--------------+
       1022.76|

1 row(s) fetched.

 

函数管理

查看函数定义

这里以 MySQL 为例,在 MySQL 中,可以使用 SHOW CREATE FUNCTION 命令查看函数的定义:

SHOW CREATE FUNCTION get_user_age;

例如,查看 get_user_age 函数的定义,在 MySQL 客户端中执行命令

mysql> SHOW CREATE FUNCTION get_user_age \G
*************************** 1. row ***************************
            Function: get_user_age
            sql_mode: ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
     Create Function: CREATE DEFINER=`root`@`%` FUNCTION `get_user_age`(birthday DATE) RETURNS int
    DETERMINISTIC
BEGIN
    -- 定义变量存储年龄
    DECLARE user_age INT;
    -- 计算年龄:当前年份 - 生日年份,若未到生日则减1
    SET user_age = YEAR(CURDATE()) - YEAR(birthday);
    IF MONTH(CURDATE()) < MONTH(birthday) OR
       (MONTH(CURDATE()) = MONTH(birthday) AND DAY(CURDATE()) < DAY(birthday)) THEN
        SET user_age = user_age - 1;
    END IF;
    -- 返回计算结果
    RETURN user_age;
END
character_set_client: utf8mb4
collation_connection: utf8mb4_0900_ai_ci
  Database Collation: utf8mb4_0900_ai_ci
1 row in set (0.00 sec)

删除函数

在 MySQL 中,可以使用 DROP FUNCTION 语句删除已经存在的函数。例如:

-- 删除 get_user_age 函数
> DROP FUNCTION IF EXISTS get_user_age

0 row(s) modified.

注意事项:

  • 创建函数需具备CREATE ROUTINE权限;

  • 函数体内避免使用SELECT *等返回结果集的语句,自定义函数仅能返回单个值;

  • 尽量保证函数是 “纯函数”(相同输入返回相同输出),便于数据库优化。

 

说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
其他应用
公众号