我的 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;
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...