CodeGym /课程 /SQL SELF /函数执行控制:PERFORM

函数执行控制:PERFORM

SQL SELF
第 55 级 , 课程 3
可用

PERFORM在PostgreSQL的世界里就像个沉默的硬核英雄,来无影去无踪,干完活就走,啥返回值都不留。这条命令就是用在你想在PL/pgSQL函数里执行SQL查询,但又不想处理或者保存结果的时候。PERFORM的主要任务就是让查询发生点啥,比如改数据或者调用另一个函数,而不是拿结果回来。

PERFORM适合用在你根本不关心查询结果的场景。和普通的SELECT不一样,SELECT会等你处理结果,PERFORM就是直接跑完查询,啥都不说就继续往下走。特别适合你只是想让函数执行一下,比如写个日志啥的。这种写法让代码更简单明了:没废话,全是重点。

PERFORM的用法例子

调用函数

来点实际的。假设我们有个log_action函数,专门把用户操作写到日志里。这个函数啥都不返回,我们只想让它执行一下。用PERFORM就是这样:

CREATE OR REPLACE FUNCTION log_action(user_id INT, action TEXT) RETURNS VOID AS $$
BEGIN
    INSERT INTO logs (user_id, action, log_time)
    VALUES (user_id, action, NOW());
END;
$$ LANGUAGE plpgsql;

-- 然后我们用PERFORM调用这个函数:
PERFORM log_action(5, '用户已登录');

这里发生了啥?PERFORM调用了log_action函数,把一条记录插进logs表。记住:函数的返回值会被忽略。我们就是为了它的副作用才用它,不是为了拿返回值。

更新数据

有时候PERFORM很适合用来执行那种你不关心结果的数据更新操作。比如,更新orders表里的订单状态:

CREATE OR REPLACE FUNCTION update_order_status(order_id INT, new_status TEXT) RETURNS VOID AS $$
BEGIN
    UPDATE orders
    SET status = new_status
    WHERE id = order_id;
END;
$$ LANGUAGE plpgsql;

-- 用PERFORM调用这个函数:
PERFORM update_order_status(101, '已发货');

这里update_order_status把ID为101的订单状态改了。我们不关心SQL查询的结果,所以PERFORM就是最佳选择。

执行辅助操作

有时候函数里会有点小操作,就是那种“辅助”逻辑,帮你把复杂流程收尾。比如,更新完表后想清一下缓存:

CREATE OR REPLACE FUNCTION clear_cache() RETURNS VOID AS $$
BEGIN
    DELETE FROM cache_table;
END;
$$ LANGUAGE plpgsql;

-- 在另一个函数里调用它:
CREATE OR REPLACE FUNCTION update_product(product_id INT, new_price NUMERIC) RETURNS VOID AS $$
BEGIN
    UPDATE products
    SET price = new_price
    WHERE id = product_id;

    -- 数据改完后清缓存:
    PERFORM clear_cache();
END;
$$ LANGUAGE plpgsql;

这就是魔法:你可以用PERFORM顺序执行一堆动作,完全不用管函数有没有返回值。

实战任务

来看看PERFORM怎么让开发者的生活更轻松。

例子1:记录过程每一步的日志

假设我们有个复杂的支付处理过程,需要记录每个阶段到日志。我们可以写个log_stage函数,然后用PERFORM

CREATE OR REPLACE FUNCTION log_stage(stage_name TEXT) RETURNS VOID AS $$
BEGIN
    INSERT INTO process_logs(stage, log_time)
    VALUES (stage_name, NOW());
END;
$$ LANGUAGE plpgsql;

-- 过程示例:
CREATE OR REPLACE FUNCTION process_payment(payment_id INT) RETURNS VOID AS $$
BEGIN
    -- 记录开始
    PERFORM log_stage('开始处理支付');

    -- 执行第一步
    UPDATE payments
    SET status = '处理中'
    WHERE id = payment_id;

    PERFORM log_stage('已更新支付状态');

    -- 执行最后一步
    UPDATE payments
    SET status = '已完成'
    WHERE id = payment_id;

    PERFORM log_stage('支付已完成');
END;
$$ LANGUAGE plpgsql;

这里log_stage通过PERFORM被调用,记录每个阶段的状态。这样代码更容易调试。

例子2:触发通知

假如你有个通知系统,每次有重要操作后都要发通知。PERFORM可以用来调用负责发通知的函数:

CREATE OR REPLACE FUNCTION send_notification(user_id INT, message TEXT) RETURNS VOID AS $$
BEGIN
    INSERT INTO notifications (user_id, message, created_at)
    VALUES (user_id, message, NOW());
END;
$$ LANGUAGE plpgsql;

-- 在过程里用:
CREATE OR REPLACE FUNCTION complete_task(task_id INT) RETURNS VOID AS $$
DECLARE
    user_id INT;
BEGIN
    -- 拿到任务负责人
    SELECT assigned_to INTO user_id
    FROM tasks
    WHERE id = task_id;

    -- 完成任务
    UPDATE tasks
    SET status = '已完成'
    WHERE id = task_id;

    -- 发送通知
    PERFORM send_notification(user_id, '你的任务已完成');
END;
$$ LANGUAGE plpgsql;

这里PERFORM让你只关注副作用——发通知,完全不用理会函数的返回值。

实用建议和常见错误

PERFORM的时候,有几个点要注意。比如,PERFORM不会检查查询有没有返回数据。意思就是,如果函数或SQL查询的结果对你的逻辑很重要,最好用SELECT INTO。比如:

-- 潜在错误
PERFORM some_function_that_must_return_value();

-- 正确做法
SELECT some_function_that_must_return_value() INTO some_variable;

另一个常见错误是,在需要结果的时候还用PERFORM,比如做数据校验。这种情况当然要拿到结果并检查。

在实际项目里,PERFORM让函数和过程更简单、更易读、更好调试。配合日志(RAISE NOTICE)和PostgreSQL自带的诊断函数,比如current_query(),它就是打造可靠、可控、易懂系统的利器。

评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION