CodeGym /课程 /SQL SELF /从SQL查询中调用函数

从SQL查询中调用函数

SQL SELF
第 50 级, 课程 2
可用

想象一下,你有个用来做复杂计算或者数据处理的函数。如果不能把函数集成进SQL查询,你得这么干:

  1. 从某个编程语言(比如Python或者JavaScript)里调用函数。
  2. 把结果传给SQL查询。

这多此一举!在PostgreSQL里,函数可以直接嵌进SQL查询里,这样代码更少,操作更快,和服务器的交互也少了。这在这些场景下特别爽:

  • 自动化计算。
  • 插入前校验数据。
  • 修改已有数据。

在SELECT里调用函数

先从基础讲起,看看怎么在普通SELECT查询里用函数。假设我们有个叫students的表,存着学生的信息。我们想写个函数,能根据出生日期返回学生当前年龄。

第1步:写函数

来写个calculate_age函数,接收出生日期,返回年龄:

CREATE OR REPLACE FUNCTION calculate_age(birth_date DATE) RETURNS INT AS $$
BEGIN
    RETURN DATE_PART('year', AGE(NOW(), birth_date))::INT;
END;
$$ LANGUAGE plpgsql;

第2步:在SELECT查询里用函数

现在我们可以对表里的每条记录调用这个函数:

SELECT id, name, calculate_age(birth_date) AS age FROM students;

发生了什么?

  • 对students表的每一行,calculate_age函数都会算出年龄。
  • 返回值会显示在age这一列。

结果示例:

id name age
1 奥托 21
2 安娜 25
3 阿列克斯 22

你看,没啥难的,结果还挺专业挺好看。

在INSERT里调用函数

插入数据时函数也很有用。比如我们有个logs表,记录用户的操作。我们想插入日志消息时,用函数自动生成文本。

第1步:写函数

写个generate_log_message函数,接收用户名和动作,返回消息文本:

CREATE OR REPLACE FUNCTION generate_log_message(username TEXT, action TEXT) RETURNS TEXT AS $$
BEGIN
    RETURN username || ' performed action: ' || action || ' at ' || NOW();
END;
$$ LANGUAGE plpgsql;

第2步:在INSERT里用函数

现在插入logs表时,直接用函数生成消息:

INSERT INTO logs (message)
VALUES (generate_log_message('奥托', '登录网站'));

结果:

id message
1 奥托 performed action: 登录网站 at 2023-10-26 12:00:00

函数帮我们搞定了文本格式和时间戳。这就是函数自动化日常操作的好例子。

在UPDATE里调用函数

函数还能用来修改表里的数据。比如我们有students表,想用函数把他们的组名升级到新年级。

第1步:写函数

写个promote_student函数,接收旧组名(比如101),返回新组名(比如201):

CREATE OR REPLACE FUNCTION promote_student(old_group TEXT) RETURNS TEXT AS $$
BEGIN
    RETURN '2' || RIGHT(old_group, LENGTH(old_group) - 1);
END;
$$ LANGUAGE plpgsql;

第2步:在UPDATE里用函数

把所有学生的组都更新一下:

UPDATE students
SET group_name = promote_student(group_name);

结果:

id name group_name
1 奥托 201
2 安娜 202
3 阿列克斯 203

你看,函数一调用,组名就自动升级了,简直像变魔术。

在WHERE条件里调用函数

函数还能用在过滤条件里。我们继续用学生年龄的例子。

第1步:按年龄过滤

用刚才写的calculate_age函数,选出大于20岁的学生:

SELECT id, name, birth_date
FROM students
WHERE calculate_age(birth_date) > 20;

结果:

id name birth_date
2 安娜 1998-05-15
3 阿列克斯 1999-11-09

这里主要就是函数帮我们实时算出每个学生的年龄。

和聚合函数一起用

来点难度。比如我们要算22岁以下学生的总数。函数和聚合函数(比如COUNT())配合得很溜。

SELECT COUNT(*)
FROM students
WHERE calculate_age(birth_date) < 22;

发生了什么?

  • calculate_age函数用来过滤。
  • COUNT(*)统计符合条件的行数。

实际应用例子

自动化数据校验。 比如你想检查表里所有学生的年龄都在正常范围(比如18到30岁)。写个校验函数,然后在WHERE条件里用它。

SELECT id, name
FROM students
WHERE NOT (calculate_age(birth_date) BETWEEN 18 AND 30);

优化数据插入。 假设你在做电商。与其在前端算订单总价,不如写个函数,直接在插入orders表时算好。

INSERT INTO orders (user_id, total_price)
VALUES (1, calculate_total_price(ARRAY[5, 10, 15]));

调用函数时常见的坑

你开始在查询里大量用函数时,可能会遇到一些坑。下面是常见的几种情况和解决办法:

没有权限。 如果你不是函数或表的owner,PostgreSQL可能不让你用。记得要有执行函数的权限。

类型不匹配。 传参数给函数时注意数据类型。比如函数要DATE,你传了字符串,就会报错。用显式类型转换:

SELECT calculate_age('2000-01-01'::DATE);

函数内部语法错。 如果函数报错,整个查询都可能挂。用之前一定要好好测试函数。

2
任务
SQL SELF, 第 50 级, 课程 2
已锁定
在 INSERT 中调用函数
在 INSERT 中调用函数
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION