使用动态查询更新表的“n”列值
Posted
技术标签:
【中文标题】使用动态查询更新表的“n”列值【英文标题】:Updating 'n' column values of table using dynamic query 【发布时间】:2015-04-16 18:54:22 【问题描述】:我有两个表,theta 和 convergence_table,每个都有相同数量的列(这里是 7 列) (w0,w1,...w6; j0,j1,...j6)。我需要将 'w' 值更新为 wn=wn-jn。在这里,我在用户定义的数据类型 wt & jt(%rowtype) 的帮助下更新了 theta 表的值。
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;
但是,现在我已经为 theta 和 convergence_table 设置了 'n+1' 列数,因此无需编写更新语句并设置所有值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
有人可以帮忙吗?
【问题讨论】:
基本上,这可以在 plpgsql 中轻松完成。但是,请先澄清任务。你想UPDATE
,但是没有定义如何匹配行。你让它看起来每个表中只有一行?在UPDATE
中,通常至少有一列未更改。如果您更改所有列,您还不如DELETE
& INSERT
- 但您仍然需要定义 what 删除...
是的,theta 和covergence 表只有单行'n'列。 Covergence 表在每次迭代中获取一组随机值,因此我必须相应地更新 theta (Wn=W(n-1)-Jn)。这就是场景。即收敛(J),theta(W)最初(null),(5,4,4,3,3,4,4)在第一次迭代之后。 (1,2,3,2,1,4,3) -> (4,2,1,1,2,0,1) 第二次迭代 (2,0,1,2,1,3,2) - > (2,2,0,-1,1,-3,-1) 我最后的 theta 表是 (2,2,0,-1,1,-3,-1)。通常我会有 1000 次迭代。
对不起,我无法附上图片,因为我只是一个初学者。 @ErwinBrandstetter
@ErwinBrandstetter,这是我的电子邮件 ID-mouryathelegend@gmail.com。请将您的邮件 ID 发给我,以便我更准确地向您解释问题。谢谢
我很欣赏这个提议,但我宁愿把它留在现场。 Edit 需要澄清的问题。
【参考方案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.
你最近一直在问一个类似的问题:
Using dynamic query + user defined datatype in Postgres有更多解释的链接。喜欢这个:
Update multiple columns in a trigger function in plpgsql【讨论】:
【参考方案2】:您可以使用 PL/pgsql EXECUTE 命令,从 information_schema.columns 构建您的查询字符串。
【讨论】:
对不起,我是 PostgreSQL 新手,不熟悉,有没有办法修改我上面的代码并得到答案? @Politank-Z ***.com/questions/9643859/… 如果我没记错的话,在这里使用 from 子句将无济于事,wt & jt 是用户定义的类型(行类型)。 & 这确实会给我另一个错误,说 jt & wt 不存在。 @Politank-Z 您可以使用 PL/pgsql 将减法的结果计算到一个数组中,并使用该数组来构造您的更新语句。以上是关于使用动态查询更新表的“n”列值的主要内容,如果未能解决你的问题,请参考以下文章