You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何此PL/pgSQL函数返回<NULL>?求技术排查方案

问题原因与修复方案

你的函数返回NULL的核心原因是**query_string变量未初始化**,PL/pgSQL中未赋值的变量默认是NULL,而NULL和任何字符串拼接结果依然是NULL,所以循环里的赋值操作根本不会改变它的值。

另外,当前代码还存在严重的SQL注入风险——直接拼接用户传入的表名、列名和值,恶意输入会直接执行危险SQL。下面是修复后的完整函数:

DROP FUNCTION IF EXISTS api.func;
CREATE OR REPLACE FUNCTION api.func
(
    _tables    json,
    conditions json
)
RETURNS text AS 
$$
DECLARE
    _key         text ; 
    _value       text ;
    _table       text ;
    where_clause text := ''; -- 初始化为空字符串
    query_parts  text[];     -- 用数组存储每个子查询,避免拼接时的UNION冗余
BEGIN
    -- 构建WHERE子句(处理空条件的情况)
    IF conditions <> '{}'::json THEN
        where_clause := 'WHERE ';
        FOR _key, _value IN
            SELECT * FROM json_each_text(conditions)
        LOOP
            -- 使用quote_ident处理列名,quote_literal处理值,防止SQL注入
            where_clause := where_clause || quote_ident(_key) || ' = ' || quote_literal(_value) || ' AND ';
        END LOOP ;
        -- 移除末尾多余的' AND '
        where_clause := rtrim(where_clause, ' AND ');
    END IF;

    -- 构建每个子查询并加入数组
    FOR _table IN
        SELECT * FROM json_array_elements_text(_tables -> 'tabnames')
    LOOP
        -- 用quote_ident处理表名,避免标识符注入
        query_parts := query_parts || format('(SELECT * FROM %s %s)', quote_ident(_table), where_clause);
    END LOOP ;

    -- 用UNION拼接所有子查询
    RETURN string_agg(unnest(query_parts), ' UNION ');
END ;
$$ LANGUAGE plpgsql ;

关键修改点说明

  1. 初始化变量:把query_string换成数组query_parts并自动初始化为空数组,若坚持用字符串则需先赋值query_string := '';。
  2. 防SQL注入:用quote_ident()处理表名、列名(避免标识符注入),quote_literal()处理值(避免值注入),或用format()函数简化拼接逻辑。
  3. 边界处理:增加空条件判断,避免生成仅含WHERE关键字的无效SQL。
  4. 更简洁的拼接方式:用数组存储子查询,最后用string_agg完成拼接,无需手动处理末尾冗余的UNION。

测试调用

执行你的测试语句:

SELECT api.func('{"tabnames" : ["tabname1", "tabname2"]}'::json, '{"col" : "val"}'::json);

会返回正确的SQL字符串:

(SELECT * FROM tabname1 WHERE "col" = 'val') UNION (SELECT * FROM tabname2 WHERE "col" = 'val')

内容的提问来源于stack exchange,提问作者eslukas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 18:54:39