For循环中的Postgresql更新

我对 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    |
+----+----------+----------+

我想编写一个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       |
+----+----------+----------+

所以最终我想循环遍历表的所有行并根据“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

我确定有一些愚蠢的东西我很想念,可能就在我身边,回归……在这种情况下无效.但是,由于我只想更新现有的行,我是否需要返回任何内容?这可能比使用循环更简单的方法,但我想让它使用这种方法.
如果有人能指出我正确的方向或指出任何明显我做错的事情,我会非常感激.
提前致谢.

解决方法

不需要循环或函数,这可以通过单个更新语句来完成:

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;

SQLFiddle:http://sqlfiddle.com/#!15/b65cb/2

你的功能没有做任何事情的原因是这样的:

update table set C = result 
WHERE id = '';

列id中没有一个空字符串的行.你的函数似乎也使用了错误的公式:当id =’a’那么B * C我猜应该是:然后a * b.由于C最初为NULL,因此b * c也将产生null.因此,即使循环中的更新会找到一行,它也会将其更新为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

但是再说一次:如果你的表格如你所说的“巨大”,那么循环是一个非常糟糕的解决方案.关系数据库用于处理数据的“集合”.逐行处理是一种反模式,几乎总是会有糟糕的性能.

或者换句话说:做基于集合的操作(比如我的单个更新示例)总是更好的选择.

相关文章

文章浏览阅读601次。Oracle的数据导入导出是一项基本的技能,...
文章浏览阅读553次。开头还是介绍一下群,如果感兴趣polardb...
文章浏览阅读3.5k次,点赞3次,收藏7次。折腾了两个小时多才...
文章浏览阅读2.7k次。JSON 代表 JavaScript Object Notation...
文章浏览阅读2.9k次,点赞2次,收藏6次。navicat 连接postgr...
文章浏览阅读1.4k次。postgre进阶sql,包含分组排序、JSON解...