PostgreSQL-常用函数和操作符-1

PostgreSQL 中文社区

  • PL/pgSQL 是 PostgreSQL 中的一种存储过程语言,它支持许多常用的函数和操作符。下面列举了一些常用的 PL/pgSQL 函数和操作符:

0. 相关概念

与NULL进行的计算操作:

  • 在SQL中,与NULL进行的计算操作通常会导致结果也是NULL,因为NULL在SQL中表示未知或缺失的数据。这种特性被称为“三值逻辑”或“NULL传播”。

具体来说:

  • 算术运算:任何涉及NULL的算术表达式的结果都是NULL。例如,5 + NULL、NULL * 10都会返回NULL。

  • 比较运算:在SQL中,当你试图比较任何值与NULL(例如,value = NULL或value <>
    NULL),结果不是TRUE或FALSE,而是UNKNOWN。这意味着条件如WHERE column = NULL或WHERE
    column <> NULL都不会匹配到任何行,除非使用IS NULL或IS NOT NULL这样的特殊谓词。

  • 逻辑运算:在某些数据库系统中,逻辑运算符与NULL的交互可能稍微复杂一些。例如,在SQL Server中,TRUE OR
    NULL的结果是TRUE,而FALSE OR NULL的结果是UNKNOWN,因为NULL被视为不确定性,而不是简单的FALSE。

因此,如果需要处理可能含有NULL值的计算或比较,应使用诸如COALESCE()、IFNULL()(在某些数据库中)、ISNULL()(特定数据库中)或CASE语句来提供默认值,或者利用IS NULL和IS NOT NULL来检查NULL值的存在。

1. 常用函数:

RAISE:用于在存储过程中抛出异常。

RAISE EXCEPTION 'Error occurred: %', error_message;

IF-ELSE:用于条件判断。

IF condition THEN
    -- do something
ELSE
    -- do something else
END IF;

CASE 语句

CASE 语句的两种基本形式:

  • 简单 CASE 表达式:
    用于将某个表达式的值与一系列离散值进行比较。
    语法1:
CASE expression  
    WHEN value1 THEN result1  
    WHEN value2 THEN result2  
    ...  
    ELSE result  
END
  • 搜索 CASE 表达式:
    用于对一系列布尔表达式进行评估。
    语法2:
CASE  
    WHEN condition1 THEN result1  
    WHEN condition2 THEN result2  
    ...  
    ELSE result  
END
  • 案例:
    假设我们有一个员工表employees,包含字段salary表示薪资,我们想要根据薪资级别给员工分配不同的奖金等级。
DO $$
DECLARE
   emp_salary numeric := 5000;  -- 假设这是某个员工的薪资
   bonus_level text;          -- 用于存储奖金等级
BEGIN
   -- 使用searched CASE根据薪资分配奖金等级
   bonus_level := CASE
      WHEN emp_salary < 3000 THEN 'Low'
      WHEN emp_salary BETWEEN 3000 AND 7000 THEN 'Medium'
      ELSE 'High'
   END;

   RAISE NOTICE 'Employee with salary % falls under bonus level: %', emp_salary, bonus_level;
END $$;

例子中,我们声明了一个变量emp_salary并赋值为5000,然后使用searched CASE结构根据薪资水平分配了不同的奖金等级。如果薪资低于3000,则奖金等级为’Low’;如果薪资在3000到7000之间,则为’Medium’;否则为’High’。最后,使用RAISE NOTICE打印出员工的薪资范围和对应的奖金等级。

FOR LOOP:用于循环操作。

FOR variable_name IN [ REVERSE ] lower_bound..upper_bound LOOP
    -- loop body
END LOOP;
  • 案例:
CREATE OR REPLACE FUNCTION print_numbers(start_num INT, end_num INT)
RETURNS VOID AS $$
DECLARE
    i INT;
BEGIN
    FOR i IN start_num..end_num LOOP
        RAISE NOTICE 'Number: %', i;
    END LOOP;
END;
$$ LANGUAGE plpgsql;

解析:

  • 这个函数名为 print_numbers,接受两个参数 start_numend_num,然后使用 FOR 循环打印从 start_numend_num 的所有数字。在循环体中,使用 RAISE NOTICE 打印每个数字的值。

WHILE LOOP:用于执行条件循环。

WHILE condition LOOP
    -- loop body
END LOOP;
  • 案例
CREATE OR REPLACE FUNCTION countdown(start_num INT)
RETURNS VOID AS $$
DECLARE
    num INT := start_num;
BEGIN
    WHILE num > 0 LOOP
        RAISE NOTICE 'Countdown: %', num;
        num := num - 1;
    END LOOP;
END;
$$ LANGUAGE plpgsql;

解析:

  • 这个函数名为 countdown,接受一个参数 start_num,然后使用 WHILE 循环实现倒计时功能。在循环体中,首先打印当前数字的值,然后将数字减一。当数字大于零时,循环继续执行,直到数字减至零为止。

RETURN:用于从函数中返回值。

RETURN value;

SELECT INTO:用于将查询结果赋值给变量。

SELECT column_name INTO variable_name FROM table_name WHERE condition;

EXECUTE:用于执行动态 SQL 语句。

EXECUTE 'SELECT * FROM ' || table_name;
  • 案例:

假设有一个存储过程,接收一个表名作为参数,并执行该表的 SELECT 查询,然后返回查询结果。

CREATE OR REPLACE FUNCTION select_from_table(table_name TEXT)
RETURNS TABLE (...) AS $$
DECLARE
    query TEXT;
BEGIN
    -- 构造动态 SQL 查询语句
    query := 'SELECT * FROM ' || table_name;
    
    -- 执行动态 SQL 查询语句
    RETURN QUERY EXECUTE query;
END;
$$ LANGUAGE plpgsql;

解析:

  • 在这个函数中,首先构造了一个动态 SQL 查询语句,然后使用 EXECUTE 执行该查询语句。最后,使用 RETURN QUERY 返回查询结果。这个函数可以接受任意表名作为参数,并执行相应的查询操作。
  • || 是字符串连接操作符,用于将两个字符串连接起来形成一个新的字符串。
  • RETURNS TABLE (...) 表示函数返回一个表类型的结果集。括号中的内容是结果集的列定义,可以包含列名和数据类型。

GET DIAGNOSTICS:用于获取异常信息。

GET DIAGNOSTICS variable_name = condition;
  • 案例:

假设有一个存储过程,执行一条 SQL 查询,并获取查询结果的行数,并将行数保存到一个变量中。

CREATE OR REPLACE FUNCTION get_row_count()
RETURNS VOID AS $$
DECLARE
    row_count INT;
BEGIN
    -- 执行查询语句
    EXECUTE 'SELECT COUNT(*) FROM your_table' INTO row_count;
    
    -- 获取查询结果的行数
    GET DIAGNOSTICS row_count = ROW_COUNT;
    
    -- 打印行数
    RAISE NOTICE 'Row count: %', row_count;
END;
$$ LANGUAGE plpgsql;

解释:

  • 在这个函数中,首先执行了一条 SQL 查询语句,然后通过 GET DIAGNOSTICS 获取查询结果的行数,并将行数保存到变量 row_count 中。最后,使用 RAISE NOTICE 打印行数。

CURSOR FOR 游标用法(了解)

注意,游标的命名必须唯一,且与其他变量和对象的名称不冲突。

  • 游标声明
DECLARE
    cursor_name CURSOR FOR
        SELECT column1, column2, ... FROM table_name WHERE condition;

在声明游标时,您指定要使用的查询,并将其分配给一个游标变量。

  • 游标打开
OPEN cursor_name;

打开游标后,它会开始执行与其关联的查询,并准备好从结果集中提取数据。

  • 循环提取数据
LOOP
    FETCH cursor_name INTO variable1, variable2, ...;
    -- 在这里对提取出的数据进行处理
    EXIT WHEN NOT FOUND;
END LOOP;

在循环中,您可以使用FETCH语句从游标中提取数据,并将其存储在指定的变量中。FETCH命令会将游标定位到结果集中的下一行数据。如果没有更多的数据可提取,则FETCH将引发一个NOT FOUND异常。您可以使用EXIT WHEN NOT FOUND语句来退出循环。

  • 关闭游标
CLOSE cursor_name;

在完成对游标的操作后,应该关闭游标以释放资源。

  • 案例1:

    • 打印当前月数据
CREATE OR REPLACE FUNCTION "myschema"."pr_date"()
  RETURNS "pg_catalog"."void" AS $BODY$
DECLARE
    v_current_month DATE := DATE_TRUNC('month', CURRENT_DATE);
    v_record users%ROWTYPE;
BEGIN
    FOR v_record IN
        SELECT * FROM users WHERE DATE_TRUNC('month', created_at) = v_current_month
    LOOP
        RAISE NOTICE 'Data: %', v_record;
    END LOOP;
    RETURN;
EXCEPTION
    WHEN others THEN
        RAISE EXCEPTION 'Error occurred: %', SQLERRM;
END;
$BODY$ LANGUAGE plpgsql;

可以优化为for查询:(结构更加清晰…)

CREATE OR REPLACE FUNCTION "myschema"."pr_dat"()
  RETURNS "pg_catalog"."void" AS $BODY$
DECLARE
    v_current_month DATE := DATE_TRUNC('month', CURRENT_DATE);
    v_record users%ROWTYPE;
BEGIN
    FOR v_record IN
        SELECT * FROM users WHERE DATE_TRUNC('month', created_at) = v_current_month
    LOOP
        RAISE NOTICE 'Data: %', v_record;
    END LOOP;
    RETURN;
EXCEPTION
    WHEN others THEN
        RAISE EXCEPTION 'Error occurred: %', SQLERRM;
END;
$BODY$ LANGUAGE plpgsql;

如果需要只需要打印某个字段,如下:

CREATE OR REPLACE FUNCTION "myschema"."pr_dat"()
  RETURNS "pg_catalog"."void" AS $BODY$
DECLARE
    v_current_month DATE := DATE_TRUNC('month', CURRENT_DATE);
    v_record TEXT; -- 设定为与 name 字段相匹配的数据类型
BEGIN
    FOR v_record IN
        SELECT name FROM users WHERE DATE_TRUNC('month', created_at) = v_current_month
    LOOP
        RAISE NOTICE 'Data: %', v_record;
    END LOOP;
    RETURN;
EXCEPTION
    WHEN others THEN
        RAISE EXCEPTION 'Error occurred: %', SQLERRM;
END;
$BODY$ LANGUAGE plpgsql;

2. 常用操作符:

:=:赋值操作符,用于将值赋给变量。

variable_name := value;

:: 直接类型转换运算符

  • 在PL/pgSQL以及PostgreSQL中,::是一个类型转换运算符。它允许你显式地将一个值从一种数据类型转换为另一种数据类型。这个操作非常直接,使用起来也很方便。
  • 案例:
    • 如:将字符串转换为数值,可以使用to_number函数或者::numeric、::integer、::float等类型转换运算符
 -- 对于整数,可以直接使用::integer:
SELECT '123'::integer;

-- 对于浮点数,可以使用::float或::numeric:
SELECT '123.45'::float;

IF-THEN-ELSE:条件判断操作符。

IF condition THEN
    -- do something
ELSE
    -- do something else
END IF;

=:相等比较操作符。

IF variable_name = value THEN
    -- do something
END IF;

!=<>:不等于比较操作符。

IF variable_name != value THEN
    -- do something
END IF;

<, >, <=, >=:大小比较操作符,用于进行大小比较。

IF variable_name < value THEN
    -- do something
END IF;

AND, OR, NOT:逻辑操作符,用于组合条件。

IF condition1 AND condition2 THEN
    -- do something
END IF;

IS NULL, IS NOT NULL:判断是否为空值。

IF variable_name IS NULL THEN
    -- do something
END IF;

LIKE, ILIKE:模糊匹配操作符,用于模式匹配。

IF variable_name LIKE 'pattern' THEN
    -- do something
END IF;
  • 案例:

假设有一个存储过程,接收一个参数,并根据参数值判断执行不同的逻辑操作。

CREATE OR REPLACE FUNCTION check_pattern(input_value TEXT)
RETURNS VOID AS $$
BEGIN
    IF input_value LIKE 'abc%' THEN
        RAISE NOTICE 'Input value starts with "abc"';
    ELSE
        RAISE NOTICE 'Input value does not start with "abc"';
    END IF;
END;
$$ LANGUAGE plpgsql;

解析:

  • 在这个函数中,使用了 LIKE 操作符来判断输入参数 input_value 是否以 “abc” 开头。如果是,则打印消息 “Input value starts with “abc””;如果不是,则打印消息 “Input value does not start with “abc””。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值