pl/pgsql:从记录中动态获取列名

Eyl*_*yla 4 postgresql plpgsql postgresql-9.3

您好,我想从记录中动态获取列名。如下面的代码所示,我创建了一个游标,并使用循环通过将每一行提取到记录类型 r1 来处理该游标中的每条记录。在我的表中,我有这些列 [dlq_2000,dlq_2001,...,dlq_2017,dlq_2017]。我还在其顶部创建了一个循环来单独处理每一列。

我面临的问题是动态从 r1 获取字段名称,当我运行代码时收到此错误:

[Err] 错误:记录“r1”没有字段“'dlq_'||counter::text”上下文:SQL 语句“SELECT (r1."'dlq_'||counter::text" = 1 )”

请建议如何解决这个问题。

谢谢你,

CREATE OR REPLACE FUNCTION update()
   RETURNS VOID AS $$
DECLARE 
cur SCROLL CURSOR   FOR select * from my_tbl;
r1 RECORD;
begin
OPEN cur ;
FOR counter IN  2000..2017 LOOP
    r1 := NULL;
    LOOP
        FETCH cur INTO r1;
        EXIT WHEN NOT FOUND;

        IF (r1."'dl_'||counter::text" = 1 ) THEN
            -- do some thing
            RAISE NOTICE 'processing year of : %', counter;
        END IF;     
    END LOOP;
END LOOP;
CLOSE cur;
END; 

 $$

LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)

Abe*_*sto 7

使用row_to_json功能

do $$
declare
  r json;
  i int;
begin
  for r in 
    select row_to_json(t.*) 
    from (values(1,'a1','a2','a3'),(2,'b1','b2','b3')) as t(x,y11,y12,y13) 
  loop
    raise info '%', r;
    for i in 11..13 loop
      if r->>('y'||i) like '%2' then -- Condition here
        raise info 'Do something for %', r->>('y'||i);
      end if;
    end loop;
  end loop;
end $$;
Run Code Online (Sandbox Code Playgroud)
信息:{“x”:1,“y11”:“a1”,“y12”:“a2”,“y13”:“a3”}
信息:为 a2 做点什么
信息:{“x”:2,“y11”:“b1”,“y12”:“b2”,“y13”:“b3”}
信息:为 b2 做点什么

使用数组构造函数

do $$
declare
  r record;
  i int;
begin
  for r in 
    select x, array[y11,y12,y13] as y 
    from (values(1,'a1','a2','a3'),(2,'b1','b2','b3')) as t(x,y11,y12,y13) 
  loop
    raise info '%', r;
    for i in 1..3 loop
      if r.y[i] like '%2' then -- Condition here
        raise info 'Do something for %', r.y[i];
      end if;
    end loop;
  end loop;
end $$;
Run Code Online (Sandbox Code Playgroud)
信息:(1,“{a1,a2,a3}”)
信息:为 a2 做点什么
信息:(2,“{b1,b2,b3}”)
信息:为 b2 做点什么

并使用数据标准化

do $$
declare
  r record;
  i int;
begin
  for r in
    with
      test as (
        select * 
        from (values(1,'a1','a2','a3'),(2,'b1','b2','b3')) as t(x,y11,y12,y13)),
      norm as (
        select *, unnest(array[y11,y12,y13]) as y, unnest(array[11,12,13]) as z from test)
    select * from norm
    where y like '%2'  -- Condition here
  loop
    raise info 'Do something for %', r;
  end loop;
end $$;
Run Code Online (Sandbox Code Playgroud)
信息:为 (1,a1,a2,a3,a2,12) 做一些事情
信息:为 (2,b1,b2,b3,b2,12) 做一些事情

有一些简化的示例,只是为了展示如何在更复杂的任务中完成它。
但在 PostgreSQL 9.5 上测试过