为什么这个函数实际上没有更新任何内容?

时间:2015-11-20 16:50:57

标签: postgresql

这是一个SQL学习练习。我有一个带有单个整数字段的'tbl'。这张桌子上没有指数。我有这个功能:

CREATE OR REPLACE FUNCTION rcs()                                                                                     
    RETURNS VOID AS $$                                                                                               
DECLARE                                                                                                              
    c CURSOR FOR SELECT * FROM tbl ORDER BY sequence;                                                                
    s INTEGER;                                                                                                       
    r RECORD;                                                                                                        
BEGIN                                                                                                                
    s := 0;                                                                                                          
    OPEN c;                                                                                                          
    LOOP                                                                                                             
        FETCH c INTO r;                                                                                              
        EXIT WHEN NOT FOUND;                                                                                         
        RAISE NOTICE 'got it';                                                                                       
        r.sequence = s;                                                                                              
        s := s + 1;                                                                                                  
        RAISE NOTICE '%', r.sequence;                                                                                
    END LOOP;                                                                                                        
    CLOSE c;                                                                                                         
END;                                                                                                                 
$$ language 'plpgsql'

这会加载并运行干净,RAISE语句表明'sequence'字段根据ORDER BY更新为0,1等。

然而,当我之后选择表时,预先存在的值(碰巧都是'6')没有改变。

这与交易有关吗?我试图摆弄COMMIT等等无济于事。

这是一个新安装的Postgresql 9.4.4,在Linode上运行,没有任何配置文件或类似的东西,来自'psql'命令行。

编辑:也许是因为'r'实际上不是数据库表,它是某种临时副本吗?如果是这样,请澄清一下,希望我在这里想要实现的目标是显而易见的(我知道这可能有点荒谬,但肯定有可能无需借助于将集合读入Java等)。

1 个答案:

答案 0 :(得分:2)

实际问题:您的函数不包含UPDATE语句,因此不会将任何内容写入磁盘。 r.sequence = s;只是为内存中的变量分配一个新值。

要解决此问题,您需要以下内容:

UPDATE tbl
   set sequence = s -- change the actual column in the table
WHERE current of c; -- for the current row of your cursor

如果where current of不起作用,您需要将其切换为"常规" where条款:

UPDATE tbl
   set sequence = s 
WHERE tbl.pk_column = r.pk_column; -- the current primary key value

但更有效的解决方案是在一个声明中执行此操作:

update tbl
   set sequence = tu.new_sequence
from ( 
    select t.pk_column, 
           row_number() over (order by t.sequence) as new_sequence
    from tbl t
) tu
where tbl.pk_column = tu.pk_column;

您需要将列名pk_column替换为表的真实主键(或唯一)列。