CodeGym /课程 /SQL SELF /分析在使用控制结构和日志时常见的错误

分析在使用控制结构和日志时常见的错误

SQL SELF
第 52 级 , 课程 4
可用

说到正题,咱们先看看你最容易踩的那些坑和小失误。毕竟SQL里的bug真的是开发者的痛,而且通常都在最不想遇到的时候冒出来。

1. 语法错误:"忘了关IF"

语法错误是最基础的毛病,但其实比你想象的还常见。比如,你忘了用END IF;IF块关掉,编译器立马就会吐槽你。

错误示例:

CREATE OR REPLACE FUNCTION check_number(num INTEGER)
RETURNS TEXT AS $$
BEGIN
    IF num > 0 THEN
        RETURN '正数';
    ELSE
        RETURN '负数';
-- somewhere lost END IF;
END;
$$ LANGUAGE plpgsql;

你要是跑这段代码,会直接报错:ERROR: syntax error at or near "END"。为啥?因为IF块没关。

怎么避免这种错?

写代码的时候结构一定要清楚。你开了个块(比如IF),就马上把结尾也写上。来看下修正后的例子:

CREATE OR REPLACE FUNCTION check_number(num INTEGER)
RETURNS TEXT AS $$
BEGIN
    IF num > 0 THEN
        RETURN '正数';
    ELSE
        RETURN '负数';
    END IF; -- 别忘了关块
END;
$$ LANGUAGE plpgsql;

2. CASE没处理所有情况:"那如果都不匹配咋办?"

CASE的时候,记得一定要加ELSE分支来兜底。没有这个分支,可能会返回NULL,让你代码出问题。

错误示例:

CREATE OR REPLACE FUNCTION grade_result(grade CHAR)
RETURNS TEXT AS $$
BEGIN
    RETURN CASE grade
        WHEN 'A' THEN '优秀'
        WHEN 'B' THEN '良好'
        WHEN 'C' THEN '一般'
        -- 那如果grade = 'D'或者别的分数呢?
    END;
END;
$$ LANGUAGE plpgsql;

你要是传个D进去,函数就会返回NULL,这可能会让你后面代码出bug。

修正写法:

CREATE OR REPLACE FUNCTION grade_result(grade CHAR)
RETURNS TEXT AS $$
BEGIN
    RETURN CASE grade
        WHEN 'A' THEN '优秀'
        WHEN 'B' THEN '良好'
        WHEN 'C' THEN '一般'
        ELSE '未知分数' -- 把剩下的都兜住
    END;
END;
$$ LANGUAGE plpgsql;

3. 死循环问题:"为啥服务器卡死了?"

LOOP循环的时候,很容易忘了写退出条件。这样就会死循环:

错误示例:

CREATE OR REPLACE FUNCTION infinite_loop_demo()
RETURNS VOID AS $$
DECLARE
    i INTEGER := 1;
BEGIN
    LOOP
        i := i + 1;
        -- 没有退出条件!
    END LOOP;
END;
$$ LANGUAGE plpgsql;

这段代码会让服务器直接卡死,因为循环永远不会停。

怎么修:

加个EXIT退出条件就行:

CREATE OR REPLACE FUNCTION finite_loop_demo()
RETURNS VOID AS $$
DECLARE
    i INTEGER := 1;
BEGIN
    LOOP
        i := i + 1;
        IF i > 10 THEN
            EXIT; -- 退出条件
        END IF;
    END LOOP;
END;
$$ LANGUAGE plpgsql;

4. 循环里漏掉了某些数据:"那漏掉的数据咋办?"

CONTINUE跳过某些循环时,如果没考虑所有情况,也会出错。比如:

错误示例:

CREATE OR REPLACE FUNCTION skip_even()
RETURNS VOID AS $$
DECLARE
    i INTEGER := 0;
BEGIN
    WHILE i < 10 LOOP
        i := i + 1;
        IF i % 2 = 0 THEN
            CONTINUE; -- 直接跳过偶数
        END IF;
        RAISE NOTICE '奇数: %', i;
    END LOOP;
END;
$$ LANGUAGE plpgsql;

要是所有数字都是偶数,服务器会跑,但你啥都看不到。

怎么修:

确保你把所有数据都处理了,加点日志方便看:

CREATE OR REPLACE FUNCTION skip_even_logging()
RETURNS VOID AS $$
DECLARE
    i INTEGER := 0;
BEGIN
    WHILE i < 10 LOOP
        i := i + 1;
        IF i % 2 = 0 THEN
            RAISE NOTICE '跳过偶数: %', i;
            CONTINUE;
        END IF;
        RAISE NOTICE '奇数: %', i;
    END LOOP;
END;
$$ LANGUAGE plpgsql;

现在你能看到哪些数字被跳过了。

5. 错误处理写错了:"我的RAISE EXCEPTION去哪了?"

RAISE EXCEPTION处理错误很强大,但写错了就会出问题。

错误示例:

CREATE OR REPLACE FUNCTION calculate_square(num INTEGER)
RETURNS INTEGER AS $$
BEGIN
    IF num < 0 THEN
        RAISE '不允许负数!';
    END IF;
    RETURN num * num;
END;
$$ LANGUAGE plpgsql;

这段代码会报错,因为RAISE语法不对(少了消息级别)。

修正写法:

CREATE OR REPLACE FUNCTION calculate_square(num INTEGER)
RETURNS INTEGER AS $$
BEGIN
    IF num < 0 THEN
        RAISE EXCEPTION '不允许负数!';
    END IF;
    RETURN num * num;
END;
$$ LANGUAGE plpgsql;

6. 日志写错了:"为啥我的错误没写进error_log?"

error_log表里写日志时,INSERT INTO写错了也会出问题。

错误示例:

CREATE OR REPLACE FUNCTION log_error(err_msg TEXT)
RETURNS VOID AS $$
BEGIN
    INSERT INTO error_log (error_message, error_time)
    VALUES (err_msg, CURRENT_TIMESTAMP); -- 要是列名错了呢?
END;
$$ LANGUAGE plpgsql;

如果error_log表的列名被改成error_msg,就会报错。

怎么避免:

一定要检查表结构,或者用严格的schema来管数据。

7. 粗心大意和"人类因素"

有些错不是技术问题,就是粗心。比如忘了删调试代码、没用的变量、代码没格式化,这些都会让你的函数变得乱七八糟。

举个例子:

DECLARE
    i INTEGER; -- 干嘛要这个变量,根本没用到!

修正:把没用的代码都删掉,让代码又干净又好懂。

现在你已经能避开PL/pgSQL里最常见的坑了,写出来的代码也会更让人开心少踩雷。记得多测、多打日志、及时修bug——这样你能省下不少心和客户电话!

1
调查/小测验
错误处理第 52 级,课程 4
不可用
错误处理
错误处理
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION