PL/pgSQL 是 "Procedural Language/PostgreSQL Structured Query Language" 的缩写
就是指 PostgreSQL 的过程化语言,它是在标准 SQL 的基础上增加了流程控制、变量声明和赋值,异常处理等其他编程功能的扩展语言,使得用户可以编写更复杂的函数和存储过程。
视图里面不涉及特定的编程语言,所以不需要指定,但是方法和存储过程需要
CREATE FUNCTION my_function() RETURNS void
LANGUAGE plpgsql
AS $$
BEGIN
-- 函数体
END;
$$;
CREATE FUNCTION my_function() RETURNS void
AS $$
BEGIN
-- 函数体
END;
$$
LANGUAGE plpgsql;
$$
$$
是一种 字符串分隔符,用于包裹函数的主体内容。它允许你定义多行字符串,并且避免了与 SQL 中的单引号 ' 产生冲突。这样做的好处是你可以在函数体中自由使用单引号,而不需要进行转义。
CREATE FUNCTION get_greeting() RETURNS TEXT
LANGUAGE plpgsql
AS '
BEGIN
RETURN ''Hello, it''s a nice day'';
END;
';
CREATE FUNCTION get_greeting() RETURNS TEXT
LANGUAGE plpgsql
AS $$
BEGIN
RETURN 'Hello, it's a nice day';
END;
$$;
可以在$$
中间加入任意字符,表示自定义分隔符,用起来和$$一样,自定义分隔符可以避免混淆
REATE FUNCTION get_greeting() RETURNS TEXT
LANGUAGE plpgsql
AS $func$
BEGIN
RETURN 'Hello, it's a nice day';
END;
$func$;
变量声明
可以通过 DECLARE 关键字来声明局部变量。变量的类型可以是 PostgreSQL 支持的任意类型,如 INTEGER、TEXT、NUMERIC、BOOLEAN 等。
DECLARE
my_variable INTEGER := 10; -- 声明一个整数变量并初始化
my_text TEXT; -- 声明一个文本变量
BEGIN
my_text := 'Hello, PL/pgSQL!';
END;
select into
SELECT INTO 语句用于将查询结果存入变量中。这是在 PL/pgSQL 中常用的语法,目的是将查询结果赋值给某个变量(即将结果存储到内存中的一个变量)。这种用法不创建新表,而是用于函数或存储过程中处理数据。
DECLARE
result INTEGER;
BEGIN
SELECT COUNT(*) INTO result FROM employees;
RAISE NOTICE 'Number of employees: %', result;
END;
而标准SQL里面,也有Select Into ,它用于将查询结果插入到一个新表中,并且在执行查询时自动创建该新表。
SELECT
employee_id,
employee_name,
department_id,
salary
INTO
temp_employees -- 创建新表 temp_employees 并插入数据
FROM
employees
WHERE
salary > 50000;
所以使用时需要注意是在标准SQL里面还是在PL/pgSQL里面
PERFORM 语句
PERFORM 语句用于执行不返回结果的查询(通常是执行函数或者查询但不关心返回值)。
BEGIN
PERFORM some_function();
END;
动态 SQL (EXECUTE)
EXECUTE 用于执行动态 SQL 语句。你可以根据运行时的需求生成 SQL 查询,并在 EXECUTE 中执行它。
DECLARE
table_name TEXT := 'employees';
sql_query TEXT;
BEGIN
sql_query := 'SELECT * FROM ' || table_name;
EXECUTE sql_query;
END;
记录与行类型 (RECORD, ROW)
RECORD 是一种动态类型,可以存储任意行的查询结果,而不需要提前知道行的结构。也就是说,RECORD 适用于返回值列数和类型未知的情况下,特别适合于处理动态的查询。只能在 PL/pgSQL 中使用,不能作为函数的返回类型。
DECLARE
rec RECORD;
BEGIN
FOR rec IN SELECT * FROM employees LOOP
RAISE NOTICE 'Employee: %', rec.name;
END LOOP;
END;
ROW 是 PostgreSQL 中的行类型(composite type),它与表中的一行记录非常相似。ROW 类型通常需要预定义具体的字段和类型,因此它是一种 静态类型。你可以将表的某一行赋值给一个 ROW 类型的变量。
- 需要明确知道行的结构(字段名和类型)。
- 常用于函数返回特定表的行或者某些字段组合。
- 可以用作函数的返回值类型。
DECLARE
emp_row employees%ROWTYPE; -- 声明一个与 employees 表相同结构的行类型
BEGIN
SELECT * INTO emp_row FROM employees WHERE id = 1;
RAISE NOTICE 'Employee ID: %, Name: %', emp_row.id, emp_row.name;
END;
返回多行 (RETURNS SETOF)
SETOF 表示返回一个集合,如果函数需要返回多个结果行,可以使用 RETURNS SETOF 来定义。SETOF 是set of的意思
CREATE FUNCTION get_employee_names() RETURNS SETOF TEXT
LANGUAGE plpgsql
AS $$
BEGIN
RETURN QUERY SELECT name FROM employees;
END;
$$;
CREATE FUNCTION get_all_employees() RETURNS SETOF employees
LANGUAGE plpgsql
AS $$
BEGIN
RETURN QUERY SELECT * FROM employees;
END;
$$;
SELECT id, name FROM get_all_employees();
数组
PL/pgSQL 支持数组的操作,你可以对数组进行遍历、添加元素等操作。
DECLARE
my_array INTEGER[] := ARRAY[1, 2, 3, 4, 5];
elem INTEGER;
BEGIN
FOREACH elem IN ARRAY my_array LOOP
RAISE NOTICE 'Element: %', elem;
END LOOP;
END;
return query
-
RETURN QUERY
用来返回 多行查询结果,它允许你返回一个结果集。
CREATE FUNCTION get_high_salary_employees(min_salary NUMERIC) RETURNS SETOF employees
LANGUAGE plpgsql
AS $$
BEGIN
RETURN SELECT * FROM employees WHERE salary > min_salary;
END;
$$;
这个函数实际上是 错误的,因为 PostgreSQL 期望在返回一个查询结果集时使用 RETURN QUERY
。简单的 RETURN
只能返回单个值或表达式,而不能处理 SQL 查询结果的返回。
-
RETURN
:用于返回单个值或单行,例如在标量函数中。CREATE FUNCTION get_employee_name(emp_id INT) RETURNS TEXT LANGUAGE plpgsql AS $$ DECLARE emp_name TEXT; BEGIN SELECT employee_name INTO emp_name FROM employees WHERE employee_id = emp_id; RETURN emp_name; -- 单行结果,直接返回 END; $$; `
-
RETURN QUERY
:用于返回多行查询结果(集合),特别是在SETOF
函数中。CREATE FUNCTION get_high_salary_employees(min_salary NUMERIC) RETURNS SETOF employees LANGUAGE plpgsql AS $$ BEGIN RETURN QUERY SELECT * FROM employees WHERE salary > min_salary; -- 返回一个结果集 END; $$;