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(),它就是打造可靠、可控、易懂系统的利器。
GO TO FULL VERSION