SQL 存储过程:从硬编码逻辑到可重用的 SQL

发布: (2026年2月2日 GMT+8 07:04)
5 min read
原文: Dev.to

Source: Dev.to

什么终于让人恍然大悟:存储过程只是可复用的逻辑

我一开始犯的错误是把存储过程当成了什么高深的东西。
它们并不是。

存储过程不过是一个有名字的 SQL 逻辑,存放在数据库里并且可以接受输入。仅此而已。

如果你已经了解:

  • 函数
  • 参数
  • if / else 逻辑

那么存储过程并不是一个全新的概念,只是一个在新环境中的新名称。

为什么普通 SQL 开始显得受限

想象一下这个非常普通的需求:

“给我所有金额超过某个数值的订单。”

在普通 SQL 中,我可能会写:

select *
from orders
where total_amount > 1000;

这样可以工作……但它是 硬编码 的。
如果规则改成 1500,我必须修改查询。
如果另一个报表需要 500,我就复制这段查询。
这种重复正是存储过程开始有意义的地方。

我的第一个有用的存储过程

create or replace procedure high_value_orders
as
begin
  select *
  from orders
  where total_amount > 1000;
end;

现在我只需要执行:

exec high_value_orders;

逻辑可以工作,但规则仍然是硬编码的。

真正的升级:参数

不要在过程内部固定数值,而是把它作为参数传入:

create or replace procedure high_value_orders (
  p_min_amount number
)
as
begin
  select *
  from orders
  where total_amount > p_min_amount;
end;

现在我可以用不同的阈值复用同一逻辑:

exec high_value_orders(500);
exec high_value_orders(1500);

这使得过程变成了可配置的行为。

CASE 出场的时刻

一开始 CASE 让我感到困惑,因为我总是看到它的抽象解释。
把它用于编码业务规则后就明白了。

示例需求: “根据客户的消费金额对其进行分类。”

select
  customer_id,
  total_spent,
  case
    when total_spent >= 5000 then 'VIP'
    when total_spent >= 2000 then 'Regular'
    else 'Occasional'
  end as customer_type
from customers;

CASE 是 SQL 版的 if / else——从上到下依次评估条件。

将 CASE 与存储过程结合

假设业务想要:

“显示客户,但根据我关心的阈值给他们贴不同的标签。”

create or replace procedure customer_segments (
  p_vip_threshold number
)
as
begin
  select
    customer_id,
    total_spent,
    case
      when total_spent >= p_vip_threshold then 'VIP'
      else 'Non-VIP'
    end as segment
  from customers;
end;

现在逻辑可以适配:

exec customer_segments(5000);
exec customer_segments(3000);

同一个过程,不同的行为。

我之前的错误做法

  • 把存储过程当成高级 SQL 语法
  • 回避参数,所有东西都硬编码
  • 把 CASE 当成技巧,而不是逻辑

把它们重新定义为:

  • 可复用的逻辑
  • 可配置的输入
  • 条件规则

一切就恍然大悟了。

为什么这超越了语法层面

SQL 不仅仅是查询数据;它还可以:

  • 强制执行规则
  • 集中管理逻辑
  • 减少重复
  • 使行为显式化

存储过程并不总是答案,但理解它们会改变你对数据库的思考方式。

结语

如果你曾觉得存储过程或 CASE 过于沉重或不必要,我能理解。
它们只有在你不再思考:

“我该怎么写这个查询?”

而开始思考:

“我该怎么让这段逻辑可复用?”

这种转变我花了一段时间才实现,但一旦实现,SQL 就不再显得浅薄。

Back to Blog

相关文章

阅读更多 »

C# 中的方法和参数使用

定义和调用方法 csharp static void Greet { Console.WriteLine'Hello!'; } static void Main { Greet; // 方法调用 } // 输出: Hello! 方法...