PostgreSQL从入门到进阶
🏠 首页
  • 开始学习

    • PostgreSQL介绍
    • 安装配置
  • 基础教程

    • 数据库与表
    • 数据类型
    • CRUD操作
    • WHERE条件
  • 进阶查询

    • 联表查询
    • 聚合函数
    • 子查询
    • 视图
  • 性能优化

    • 索引优化
    • 查询优化
    • EXPLAIN分析
  • 事务处理
  • 触发器
  • 存储过程
  • JSON数据
  • 博客系统
  • 用户管理系统
  • 最佳实践
🔗 编程指南
🏠 首页
  • 开始学习

    • PostgreSQL介绍
    • 安装配置
  • 基础教程

    • 数据库与表
    • 数据类型
    • CRUD操作
    • WHERE条件
  • 进阶查询

    • 联表查询
    • 聚合函数
    • 子查询
    • 视图
  • 性能优化

    • 索引优化
    • 查询优化
    • EXPLAIN分析
  • 事务处理
  • 触发器
  • 存储过程
  • JSON数据
  • 博客系统
  • 用户管理系统
  • 最佳实践
🔗 编程指南
  • 开始之前

    • 教程介绍
    • 什么是PostgreSQL?
    • 安装PostgreSQL
  • 基础入门

    • 数据库和表的概念
    • 数据类型详解
    • 增删改查操作(CRUD)
    • 查询条件WHERE
  • 进阶查询

    • 多表联查JOIN
    • 聚合函数
    • 子查询
    • 视图VIEW
  • 性能优化

    • 索引详解
    • 查询优化
    • 执行计划分析
  • 高级特性

    • 事务处理
    • 触发器
    • 存储过程
    • JSON数据
  • 实战项目

    • 实战项目:博客系统
    • 实战项目:用户管理系统
    • 最佳实践

存储过程

嗨!长安来讲存储过程!把逻辑放进数据库!

🎯 什么是存储过程?

存储过程是保存在数据库中的SQL代码,可以重复调用。

-- 创建函数
CREATE OR REPLACE FUNCTION get_user_posts(user_id INT)
RETURNS TABLE(title VARCHAR, created_at TIMESTAMP) AS $$
BEGIN
    RETURN QUERY
    SELECT p.title, p.created_at
    FROM posts p
    WHERE p.user_id = get_user_posts.user_id
    ORDER BY p.created_at DESC;
END;
$$ LANGUAGE plpgsql;

-- 调用函数
SELECT * FROM get_user_posts(1);

📝 创建函数

简单函数

-- 计算两数之和
CREATE OR REPLACE FUNCTION add_numbers(a INT, b INT)
RETURNS INT AS $$
BEGIN
    RETURN a + b;
END;
$$ LANGUAGE plpgsql;

-- 调用
SELECT add_numbers(10, 20);  -- 结果:30

返回表格

CREATE OR REPLACE FUNCTION search_products(keyword VARCHAR)
RETURNS TABLE(id INT, name VARCHAR, price DECIMAL) AS $$
BEGIN
    RETURN QUERY
    SELECT p.id, p.name, p.price
    FROM products p
    WHERE p.name ILIKE '%' || keyword || '%';
END;
$$ LANGUAGE plpgsql;

-- 调用
SELECT * FROM search_products('phone');

带OUT参数

CREATE OR REPLACE FUNCTION get_user_stats(
    user_id INT,
    OUT post_count INT,
    OUT comment_count INT
) AS $$
BEGIN
    SELECT COUNT(*) INTO post_count FROM posts WHERE user_id = user_id;
    SELECT COUNT(*) INTO comment_count FROM comments WHERE user_id = user_id;
END;
$$ LANGUAGE plpgsql;

-- 调用
SELECT * FROM get_user_stats(1);

💡 控制语句

IF条件

CREATE OR REPLACE FUNCTION check_stock(product_id INT, quantity INT)
RETURNS TEXT AS $$
DECLARE
    current_stock INT;
BEGIN
    SELECT stock INTO current_stock FROM products WHERE id = product_id;
    
    IF current_stock >= quantity THEN
        RETURN '库存充足';
    ELSIF current_stock > 0 THEN
        RETURN '库存不足';
    ELSE
        RETURN '无库存';
    END IF;
END;
$$ LANGUAGE plpgsql;

LOOP循环

CREATE OR REPLACE FUNCTION generate_sequence(n INT)
RETURNS SETOF INT AS $$
DECLARE
    i INT := 1;
BEGIN
    LOOP
        EXIT WHEN i > n;
        RETURN NEXT i;
        i := i + 1;
    END LOOP;
END;
$$ LANGUAGE plpgsql;

FOR循环

CREATE OR REPLACE FUNCTION sum_to_n(n INT)
RETURNS INT AS $$
DECLARE
    total INT := 0;
    i INT;
BEGIN
    FOR i IN 1..n LOOP
        total := total + i;
    END LOOP;
    RETURN total;
END;
$$ LANGUAGE plpgsql;

🎮 实战案例

转账函数

CREATE OR REPLACE FUNCTION transfer_money(
    from_user INT,
    to_user INT,
    amount DECIMAL
) RETURNS BOOLEAN AS $$
DECLARE
    from_balance DECIMAL;
BEGIN
    -- 检查余额
    SELECT balance INTO from_balance 
    FROM accounts WHERE user_id = from_user;
    
    IF from_balance < amount THEN
        RAISE EXCEPTION '余额不足';
    END IF;
    
    -- 转账
    UPDATE accounts SET balance = balance - amount 
    WHERE user_id = from_user;
    
    UPDATE accounts SET balance = balance + amount 
    WHERE user_id = to_user;
    
    -- 记录日志
    INSERT INTO transfer_logs (from_user, to_user, amount, created_at)
    VALUES (from_user, to_user, amount, NOW());
    
    RETURN TRUE;
END;
$$ LANGUAGE plpgsql;

-- 使用
SELECT transfer_money(1, 2, 100.00);

📚 下一步

存储过程能封装复杂逻辑,但要适度使用!

继续学习JSON数据!


长安的建议:简单逻辑用SQL,复杂逻辑用应用代码!平衡很重要!💡

最近更新: 2025/12/1 18:21
Prev
触发器
Next
JSON数据