正在开发中的 PostgreSQL 17 即将增加一个新功能:PL/pgSQL 支持定义伪类型 %TYPE以及%ROWTYPE 数组。
当我们使用 PL/pgSQL 编写存储过程或者函数时,可以定义不同类型的变量。例如:
user_id integer;
quantity numeric(5);
url varchar;
myrow tablename%ROWTYPE;
myfield tablename.columnname%TYPE;
arow RECORD;
在此基础上,我们可以通过 %TYPE 以及 %ROWTYPE 定义伪类型,例如:
user_id users.user_id%TYPE;
user_row users%ROWTYPE;
变量 user_id 的类型基于字段 users.user_id 的类型,user_row 的类型基于表 users 的行类型。这种伪类型的好处是表的字段类型发生变化时,代码不需要改动。
PostgreSQL 17 开始,我们可以定义这种伪类型的数组变量,例如:
DO $$
DECLARE
v_all_db_names pg_database.datname%TYPE[];
v_all_dbs pg_database%ROWTYPE[];
BEGIN
SELECT array_agg(datname) INTO v_all_db_names FROM pg_database;
SELECT array_agg(d) INTO v_all_dbs FROM pg_database d;
raise notice 'All db names = %', v_all_db_names;
raise notice 'All dbs = %', v_all_dbs;
END;
$$;
NOTICE: ALL db names = {postgres,template1,template0,pgdba,depesz}
NOTICE: ALL dbs = {"(5,postgres,10,6,c,f,t,f,-1,728,1,1663,en_US.UTF-8,en_US.UTF-8,,,2.37,)","(1,template1,10,6,c,t,t,f,-1,728,1,1663,en_US.UTF-8,en_US.UTF-8,,,2.37,\"{=c/pgdba,pgdba=CTc/pgdba}\")","(4,template0,10,6,c,t,f,f,-1,728,1,1663,en_US.UTF-8,en_US.UTF-8,,,,\"{=c/pgdba,pgdba=CTc/pgdba}\")","(16462,pgdba,10,6,c,f,t,f,-1,728,1,1663,en_US.UTF-8,en_US.UTF-8,,,2.37,)","(16473,testdb,16384,6,c,f,t,f,-1,728,1,1663,en_US.UTF-8,en_US.UTF-8,,,2.37,)"}
DO
其中,v_all_db_names 变量是一个字符串数组,元素的类型锚定了 pg_database.datname 的类型。v_all_dbs 是一个行数组,元素的类型锚定了 pg_database%ROWTYPE 行类型。