这节课我们来看看PL/pgSQL支持哪些数据类型,以及怎么高效地用它们。主要关注这四种类型:
INTEGER用来搞定数字。TEXT处理字符串。BOOLEAN处理布尔值。RECORD处理动态数据结构。
每种类型我们都会用例子讲解,这样你能看到它们实际怎么用。
PL/pgSQL支持的数据类型
PL/pgSQL支持你在PostgreSQL里见过的所有数据类型。从简单的数字类型(INTEGER、NUMERIC)到更复杂的,比如数组和JSONB。我们来快速过一下常用的。
基础类型:
INTEGER、BIGINT、FLOAT、NUMERIC—— 数字类型。TEXT、CHAR、VARCHAR—— 字符串类型。BOOLEAN—— 布尔类型。
复杂类型:
RECORD—— 用来处理动态数据集。ROWTYPE—— 用来处理表的行类型。- 数组和JSON —— 这些我们后面课程会讲。
INTEGER类型的用法
INTEGER 是最常用的数据类型之一。它用来存整数。在PL/pgSQL里你可以用它来做计算、处理记录ID、判断条件啥的。
例子:统计记录数量
比如说,我们有个students表,想知道数据库里有多少学生。
DO $$
DECLARE
total_students INTEGER; -- 用来存学生数量的变量
BEGIN
SELECT COUNT(*) INTO total_students FROM students; -- 查询结果存到变量里
RAISE NOTICE '学生数量: %', total_students; -- 打印消息
END;
$$;
用INTEGER时要注意:
- 在PL/pgSQL里,变量赋值要用
INTO关键字。 - 如果你想把小数存进
INTEGER,会报错。遇到这种情况用NUMERIC或FLOAT吧。
TEXT类型的用法
TEXT用来存字符串数据。比如名字、描述或者各种文本都能用它。
例子:打印学生名字
这个例子里我们把students表里所有学生的名字都打印出来。
DO $$
DECLARE
student_name TEXT; -- 存学生名字的变量
BEGIN
FOR student_name IN SELECT name FROM students LOOP
RAISE NOTICE '学生名字: %', student_name; -- 打印每个名字
END LOOP;
END;
$$;
处理TEXT时常用的函数:
UPPER()和LOWER()—— 转大写/小写。CONCAT()—— 拼接字符串。LENGTH()—— 字符串长度。
比如:
DO $$
DECLARE
full_name TEXT;
BEGIN
full_name := CONCAT('阿列克斯', ' 明'); -- 拼接字符串
RAISE NOTICE '全名: %', UPPER(full_name); -- 打印大写名字
END;
$$;
BOOLEAN类型的用法
BOOLEAN用来存布尔值:TRUE、FALSE和NULL。这个类型在判断条件和数据过滤时特别有用。
例子:检查学生是否活跃
比如你有个students表,里面有个is_active字段,表示学生是不是活跃。
DO $$
DECLARE
is_active BOOLEAN; -- 存活跃状态的变量
BEGIN
SELECT is_active INTO is_active FROM students WHERE id = 1; -- 从表里取值
IF is_active THEN
RAISE NOTICE '学生是活跃的!';
ELSE
RAISE NOTICE '学生不活跃。';
END IF;
END;
$$;
用BOOLEAN时要注意:
- 布尔值可以直接用在
IF和WHILE条件里。 NULL在逻辑判断里算“未定义”,所以判断时要注意。
RECORD类型的用法
RECORD是个很强的数据类型,用来存没有预先定义结构的数据行。你在处理SQL查询结果(返回多列)时特别有用。
例子:遍历表的所有记录
下面这个例子我们遍历students表的所有记录,打印每个学生的名字和ID。
DO $$
DECLARE
student RECORD; -- 用来存一行数据的动态类型
BEGIN
FOR student IN SELECT id, name FROM students LOOP
RAISE NOTICE 'ID: %, 名字: %', student.id, student.name; -- 访问记录的字段
END LOOP;
END;
$$;
用RECORD时要注意:
RECORD类型的变量只能在循环里或者用SELECT INTO时赋值。- 访问字段用
record.字段名。
用ROWTYPE类型处理表数据
如果你想把表里的一整行都存下来(而且想要强类型),可以用ROWTYPE。它会自动继承表的结构。
例子:用ROWTYPE类型
DO $$
DECLARE
student students%ROWTYPE; -- 变量结构和students表一模一样
BEGIN
SELECT * INTO student FROM students WHERE id = 1; -- 把一行数据存进变量
RAISE NOTICE '学生名字: %, 课程: %', student.name, student.course;
END;
$$;
RECORD和ROWTYPE的区别
| 特点 | RECORD | ROWTYPE |
|---|---|---|
| 字段结构 | 事先没定义 | 跟表或查询结构走 |
| 用法 | 啥结果都能装,灵活 | 结构死板,和表绑定 |
实战例子
我们来写个函数,返回所有活跃学生的数量和名字。
CREATE FUNCTION active_students_report() RETURNS TABLE(id INT, name TEXT) AS $$
BEGIN
RETURN QUERY
SELECT id, name FROM students WHERE is_active = TRUE;
END;
$$ LANGUAGE plpgsql;
调用函数:
SELECT * FROM active_students_report();
用数据类型时常见的错误
有时候用数据会出错。下面这些是常见的坑:
- 类型错误:比如把字符串赋值给
INTEGER变量(比如my_var := 'abc';)。 - 在需要
TRUE或FALSE的地方用了NULL。 - 用
RECORD时没初始化好。
怎么避免这些错误:
- 变量类型一定要写清楚。
- 写入表前先检查字段类型。
- 多用
RAISE NOTICE这种调试命令。
现在你已经会用PL/pgSQL里的INTEGER、TEXT、BOOLEAN和RECORD类型了。这些知识能帮你写出更复杂、更强大的PostgreSQL存储过程和函数。
GO TO FULL VERSION