WHILE 循环出错? PL/pgSQL_postgresv10

问题描述 投票:0回答:1

我的 PL/pgSQL 脚本 (postgres v10) 有问题。 目标很简单:列出数据库的模式、每个模式的表及其记录数+每个表的哈希值。 我遇到的问题是对于大表,我“内存不足”。经过一番研究后,我编写了批量操作的代码。然而,当测试代码时,它告诉我错误

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 < 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;
postgresql while-loop plpgsql
1个回答
0
投票

offset
是SQL中的保留字。您可以将其替换为非保留字的名称,例如
curr_offset
,应该没问题:

curr_offset := 0;
EXECUTE format('SELECT COUNT(*) FROM %I.%I', schema_rec.schema_name, table_rec.table_name)
INTO row_count;

WHILE curr_offset < row_count LOOP
    -- etc...
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.