使用动态查询更新表的'n'列值

时间:2015-04-16 18:54:23

标签: sql postgresql sql-update plpgsql dynamic-sql

我有两个表, theta convergence_table ,每个表都有相同的列数(此处有7列) (w0,w1,... w6; j0,j1,... j6)。我需要更新' w'值为 wn = wn-jn 。在这里,我借助用户定义的数据类型 wt&更新theta表的值。 JT(%ROWTYPE)

select * into jt from convergence_table;                 
select * into wt from theta

update theta                            
    set w0 =  wt.w0-jt.j0, w1 =  wt.w1-jt.j1, w2 =  wt.w2-jt.j2,    
        w3 =  wt.w3-jt.j3, w4 =  wt.w4-jt.j4, w5 =  wt.w5-jt.j5, 
        w6 =  wt.w6-jt.j6;

但是,现在我已经' n + 1' theta &的列数 convergence_table ,因此不是编写更新语句并设置 w0,w1,w2 .... wn 的所有值。有没有办法编写动态查询来执行从 w0 wn 的所有列值的更新。

我正在尝试以下代码,但它不起作用..

create or replace function sample(c int)
returns void as $$
declare jt convergence_table%rowtype; wt theta%rowtype;  
    query1 text:=''; query2 text:='';

begin

    select * into jt from convergence_table;                
    select * into wt from theta;

    for i in 0..n 
    loop
        query1 := query1 ||'w'||i||' = '||
        'wt.w'||i||' - jt.j'||i||',';
        end loop;

    query2 := trim(trailing ',' from query1);
    query2 := 'update theta set '||query2||';';
    execute query2;

return;
end;
$$ language plpgsql;

这给了我一个错误......

ERROR:  missing FROM-clause entry for table "wt"
LINE 1: update theta set w0 = wt.w0 - jt.j0,w1 = wt.w1 - jt.j1,w2 = ...
                              ^
QUERY:  update theta set w0 = wt.w0 - jt.j0,w1 = wt.w1 - jt.j1,w2 = wt.w2 - jt.j2,w3 = wt.w3 - jt.j3,w4 = wt.w4 - jt.j4,w5 = wt.w5 - jt.j5,w6 = wt.w6 - jt.j6;
CONTEXT:  PL/pgSQL function sample(integer) line 20 at EXECUTE statement

********** Error **********

ERROR: missing FROM-clause entry for table "wt"
SQL state: 42P01
Context: PL/pgSQL function sample(integer) line 20 at EXECUTE statement

任何人都可以帮忙吗?

2 个答案:

答案 0 :(得分:1)

CREATE OR REPLACE FUNCTION f_upd_dyn(_source regclass, _target regclass)
  RETURNS void AS
$func$
DECLARE
   source_cols text;
   target_cols text;
BEGIN
   SELECT INTO source_cols
          string_agg(quote_ident(attname), ', s.' ORDER BY attname)
   FROM   pg_attribute
   WHERE  attrelid = _source
   AND    NOT attisdropped              -- no dropped (dead) columns
   AND    attnum > 0;                   -- no system columns

   SELECT INTO target_cols
          string_agg(quote_ident(attname), ', ' ORDER BY attname)
   FROM   pg_attribute
   WHERE  attrelid = _target
   AND    NOT attisdropped              -- no dropped (dead) columns
   AND    attnum > 0;                   -- no system columns

   EXECUTE format('UPDATE %s t
                   SET   (%s) = (s.%s)  -- prepend 1st table qual s.
                   FROM  %s s' 
                  -- WHERE t.? = s.?    -- how to join source and target?
                 , _target::text, target_cols
                 , source_cols, _source::text
                 );
END
$func$ LANGUAGE plpgsql;

呼叫:

SELECT f_upd_dyn('convergence_table', 'theta');

生成并执行如下代码:

UPDATE theta t SET (w1, w2, w3) = (s.j1, s.j2, s.j3)
FROM convergence_table s
-- note the missing WHERE condition!

SQL Fiddle.

你最近一直在问类似的问题:

有更多解释的链接。像这样:

答案 1 :(得分:0)

您可以使用PL / pgsql EXECUTE命令,从information_schema.columns构建查询字符串。