tas*_*ear 3 postgresql for-loop sql-update
我对postgresql很新,我在使用for循环更新表中的空值列时遇到问题.我正在努力的表是巨大的,所以为了简洁,我将给出一个更小的例子,它应该得到重点.请参考下表
+----+----------+----------+
| id | A | B | C |
+----+----------+----------+
| a | 1 | 0 | NULL |
| b | 1 | 1 | NULL |
| c | 2 | 4 | NULL |
| a | 3 | 2 | NULL |
| c | 2 | 3 | NULL |
| d | 4 | 2 | NULL |
+----+----------+----------+
Run Code Online (Sandbox Code Playgroud)
我想编写一个for循环,遍历所有行并对列a和b中的值执行一些操作,然后在c中插入一个新值.例如,在id = a的情况下,更新表集合C = A*B,或者其中id = d设置C = A + B等.这样就会给我一个表格
+----+----------+----------+
| id | A | B | C |
+----+----------+----------+
| a | 1 | 0 | 0 |
| b | 1 | 1 | NULL |
| c | 2 | 4 | NULL |
| a | 3 | 2 | 6 |
| c | 2 | 3 | NULL |
| d | 4 | 2 | 6 |
+----+----------+----------+
Run Code Online (Sandbox Code Playgroud)
所以最终我想循环遍历表的所有行并根据"id"列中的值更新列C. 我写的函数(没有给出任何错误但也没有更新任何内容)看起来像这样......
-- DROP FUNCTION some_function();
CREATE OR REPLACE FUNCTION some_function()
RETURNS void AS
$BODY$
DECLARE
--r integer; not too sure if this needs to be declared or not
result int;
BEGIN
FOR r IN select * from 'table_name'
LOOP
select(
case
when id = 'a' THEN B*C
when id = 'd' THEN B+C
end)
into result;
update table set C = result
WHERE id = '';
END LOOP;
RETURN;
END
$BODY$
LANGUAGE plpgsql
Run Code Online (Sandbox Code Playgroud)
我确定有一些愚蠢的东西我很想念,可能就在我身边,回归......在这种情况下无效.但是,由于我只想更新现有的行,我是否需要返回任何内容?这可能比使用循环更简单的方法,但我想让它使用这种方法.如果有人能指出我正确的方向或指出任何明显我做错的事情,我会非常感激.提前致谢.
不需要循环或函数,这可以使用单个update语句完成:
update table_name
set c = case
when id = 'a' then a*b
when id = 'd' then a+b
else c -- don't change anything
end;
Run Code Online (Sandbox Code Playgroud)
SQLFiddle:http://sqlfiddle.com/#!15/b65cb/2
你的功能没有做任何事情的原因是这样的:
update table set C = result
WHERE id = '';
Run Code Online (Sandbox Code Playgroud)
列中没有包含空字符串的行id.你的功能似乎也使用了错误的公式:when id = 'a' THEN B*C我猜应该是:then a*b.由于C是NULL初期,b*c也会产生空.因此,即使当你在循环更新会发现一排,将更新它NULL.
您还从光标中错误地检索值.
如果你真的,真的想在循环中低效地执行它,你的函数应该看起来像这样(未经测试!):
CREATE OR REPLACE FUNCTION some_function()
RETURNS void AS
$BODY$
DECLARE
result int;
BEGIN
-- r is a structure that contains an element for each column in the select list
FOR r IN select * from table_name
LOOP
if r.id = 'a' then
result := r.a * r.b;
end if;
if r.id = 'b' then
result := r.a + r.b;
end if;
update table
set C = result
WHERE id = r.id; -- note the where condition that uses the value from the record variable
END LOOP;
END
$BODY$
LANGUAGE plpgsql
Run Code Online (Sandbox Code Playgroud)
但是再说一次:如果你的表格如你所说的"巨大",那么循环是一个非常糟糕的解决方案.关系数据库用于处理数据的"集合".逐行处理是一种反模式,几乎总是会有糟糕的性能.
或者换句话说:做基于集合的操作(就像我的单个update例子)总是更好的选择.
| 归档时间: |
|
| 查看次数: |
14795 次 |
| 最近记录: |