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

PostgreSQL 10 PL/pgSQL脚本WHILE循环语法错误求助

问题排查:PostgreSQL 10 PL/pgSQL脚本WHILE循环语法错误

我在PostgreSQL 10环境下编写PL/pgSQL脚本,需求为列出数据库非系统模式、各模式下的基表,以及每个表的行数与MD5哈希值。因大表处理时内存溢出,改为分批处理后,测试时WHILE循环处报错:

ERROR: syntax error at or near "<"
WHILE offset < row_count LOOP

注释循环后代码可正常运行,原脚本代码如下:

CREATE OR REPLACE FUNCTION verify_migration()
RETURNS TABLE (schema_name TEXT, table_name TEXT, row_count BIGINT, table_md5 TEXT) AS $$
DECLARE
    schema_rec RECORD;
    table_rec RECORD;
    row_count BIGINT;
    batch_size INTEGER := 10000;
    offset INTEGER := 0;
    table_md5 TEXT;
    batch_md5 TEXT;
BEGIN
    FOR schema_rec IN
        SELECT s.schema_name
        FROM information_schema.schemata s
        WHERE s.schema_name NOT IN ('pg_catalog', 'information_schema')
    LOOP
        FOR table_rec IN
            SELECT t.table_name
            FROM information_schema.tables t
            WHERE t.table_schema = schema_rec.schema_name
              AND t.table_type = 'BASE TABLE'
        LOOP
            table_md5 := '';
            offset := 0;
            EXECUTE format('SELECT COUNT(*) FROM %I.%I', schema_rec.schema_name, table_rec.table_name)
            INTO row_count;

            WHILE offset &lt; row_count LOOP
                EXECUTE format('
                    SELECT md5(string_agg(t::text, ''''))
                    FROM (
                        SELECT *
                        FROM %I.%I
                        ORDER BY 1
                        LIMIT %L OFFSET %L
                    ) t', schema_rec.schema_name, table_rec.table_name, batch_size, offset)
                INTO batch_md5;
                
                IF batch_md5 IS NOT NULL THEN
                    table_md5 := md5(COALESCE(table_md5, '') || batch_md5);
                END IF;
                
               offset := offset + batch_size;
            END LOOP;
            
            RETURN QUERY
            SELECT
                schema_rec.schema_name::TEXT,       -- Cast explicite en TEXT
                table_rec.table_name::TEXT,         -- Cast explicite en TEXT
                row_count,                          -- deja un BIGINT
                table_md5;                          -- déjà en type TEXT
        END LOOP;
    END LOOP;
END $$ LANGUAGE plpgsql;

错误原因

脚本中WHILE循环条件里的&lt;是HTML转义字符,PL/pgSQL无法识别这个转义后的符号,必须直接使用原生的小于号<。

修正后的脚本

CREATE OR REPLACE FUNCTION verify_migration()
RETURNS TABLE (schema_name TEXT, table_name TEXT, row_count BIGINT, table_md5 TEXT) AS $$
DECLARE
    schema_rec RECORD;
    table_rec RECORD;
    row_count BIGINT;
    batch_size INTEGER := 10000;
    offset INTEGER := 0;
    table_md5 TEXT;
    batch_md5 TEXT;
BEGIN
    FOR schema_rec IN
        SELECT s.schema_name
        FROM information_schema.schemata s
        WHERE s.schema_name NOT IN ('pg_catalog', 'information_schema')
    LOOP
        FOR table_rec IN
            SELECT t.table_name
            FROM information_schema.tables t
            WHERE t.table_schema = schema_rec.schema_name
              AND t.table_type = 'BASE TABLE'
        LOOP
            table_md5 := '';
            offset := 0;
            EXECUTE format('SELECT COUNT(*) FROM %I.%I', schema_rec.schema_name, table_rec.table_name)
            INTO row_count;

            WHILE offset < row_count LOOP
                EXECUTE format('
                    SELECT md5(string_agg(t::text, ''''))
                    FROM (
                        SELECT *
                        FROM %I.%I
                        ORDER BY 1
                        LIMIT %L OFFSET %L
                    ) t', schema_rec.schema_name, table_rec.table_name, batch_size, offset)
                INTO batch_md5;
                
                IF batch_md5 IS NOT NULL THEN
                    table_md5 := md5(COALESCE(table_md5, '') || batch_md5);
                END IF;
                
               offset := offset + batch_size;
            END LOOP;
            
            RETURN QUERY
            SELECT
                schema_rec.schema_name::TEXT,       -- 显式转换为TEXT
                table_rec.table_name::TEXT,         -- 显式转换为TEXT
                row_count,                          -- 已是BIGINT类型
                table_md5;                          -- 已是TEXT类型
        END LOOP;
    END LOOP;
END $$ LANGUAGE plpgsql;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 08:20:20