在大多数 SQL 实现中(例如,T-SQL、PL/pgSQL、PL/SQL),控制结构是可用的:条件(IF/CASE)、循环(WHILE/FOR/LOOP)、错误处理构造。它们在服务器上自动化业务逻辑时很方便——例如,用于生成复杂报告、验证业务规则、协调 ETL 过程和自动响应事件。
然而,在 SQL 过程中过度使用循环和复杂条件可能导致可读性和性能的下降(将 SQL 变成“命令式地狱”——过程地狱的效果)。
建议仅在无法通过网络(基于集)处理实现的操作中使用这些结构:例如,逐条处理带有动态逻辑的记录。
CREATE PROCEDURE ProcessOrders AS BEGIN DECLARE @OrderID INT, @Total FLOAT DECLARE OrderCursor CURSOR FOR SELECT OrderID FROM Orders WHERE Status = 'NEW' OPEN OrderCursor FETCH NEXT FROM OrderCursor INTO @OrderID WHILE @@FETCH_STATUS = 0 BEGIN SELECT @Total = SUM(Price) FROM OrderItems WHERE OrderID = @OrderID IF @Total > 10000 UPDATE Orders SET Status='MANUAL_CHECK' WHERE OrderID=@OrderID ELSE UPDATE Orders SET Status='APPROVED' WHERE OrderID=@OrderID FETCH NEXT FROM OrderCursor INTO @OrderID END CLOSE OrderCursor DEALLOCATE OrderCursor END
在 SELECT 中,CASE 是否可以替代嵌套的 IF 条件,并且它们是否可以互换?
答复:不可以。CASE 只能在 SELECT/UPDATE/INSERT 表达式中用于计算字段。IF 只用于过程/函数/触发器的控制块中,在“纯” SELECT 中不允许。
示例:
SELECT CASE WHEN score > 80 THEN 'High' ELSE 'Low' END AS Level FROM students -- IF 在这里是不可能的
故事
团队试图将整个业务流程从代码重写到 SQL 程序中,使用大量嵌套的 IF/ELSE 和循环。结果——代码复杂且难以调试,维护几乎不可能。转向将逻辑移回应用程序,仅保留关键过程。
故事
在 PL/pgSQL 中,由于错误使用 LOOP 而未正确退出(EXIT),导致存储过程出现“无限”循环,阻塞了与数据库的连接。通过实施循环重复限制和正确的退出条件来解决。
故事
在处理订单的过程中嵌套 IF 的逻辑错误:缺少 ELSE 结构。一些订单保持在不正确的状态(NULL),缺少后续验证。添加了明确默认行为的点情况 ELSE。