Sql 在Postgres 8.4中,每行调用一次函数进行更新

Sql 在Postgres 8.4中,每行调用一次函数进行更新,sql,database,postgresql,sql-update,Sql,Database,Postgresql,Sql Update,我有以下更新声明: update mytable set a = first_part(genid()), b = second_part(genid()), c = third_path(genid()) where package_id = 10; 在本例中,函数genid()对每一行调用三次,这是错误的-我希望对mytable的每一行只调用一次 我正在使用PostgreSQL 8.4数据库。如何编写正确的更新 我试过这样的方法: update myta

我有以下更新声明:

update mytable
   set a = first_part(genid()),
       b = second_part(genid()),
       c = third_path(genid())
 where package_id = 10;
在本例中,函数
genid()
对每一行调用三次,这是错误的-我希望对
mytable
的每一行只调用一次

我正在使用PostgreSQL 8.4数据库。如何编写正确的更新

我试过这样的方法:

update mytable
   set a = first_part(g),
       b = second_part(g),
       c = third_path(g)
 where package_id = 10
  from genid() as g;

但是它不起作用,因为整个update语句只调用了
genid()
一次

您尝试过Postgres的非标准
更新吗。。FROM
子句?我想,这会管用的

update mytable
   set a = first_part(gen.id),
       b = second_part(gen.id),
       c = third_path(gen.id)
  from (
          select genid() as genid, id
          from mytable 
          where package_id = 10
       ) gen
 where mytable.id = gen.id;
 --and package_id = 10 -- This predicate is no longer necessary as the subquery
                       -- already filters on package_id, as Erwin mentioned
请注意,我正在强制子选择中的
mytable
中的每个记录只调用一次
genid()
。然后我使用一个假设的
id
列自连接
mytable
gen
。 请参阅此处的文档:


不过,这似乎只是在Postgres 9.0中引入的。如果这看起来太复杂(即不太可读),您仍然可以使用pgplsql作为用户。

您能检查一下这在postgres中是否有效吗

update 
  (select 
     a, b, c, genid() as val
  from mytable
  where package_id = 10
  )
set a = first_part(val),
       b = second_part(val),
       c = third_path(val);
更新: 你能用光标试试吗

DECLARE c1 CURSOR FOR 
      select 
         a, b, c, genid() as val
      from mytable
      where package_id = 10; 
...
UPDATE table SET ... WHERE CURRENT OF c1;

我建议使用以下方法-

DECLARE @genID VARCHAR(100) -- or appropriate datatype

SET @genID = genid() -- Or select @genID = genid()    
update mytable    
   set a = first_part(@genID),
       b = second_part(@genID),
       c = third_path(@genID)
where package_id = 10; 

你不能把它放在一个存储过程中,然后首先调用
genid()
,将它存储在一个变量中,然后在你的update语句中使用它吗?你太简化了这个例子,我怀疑你有gen_id(column)@Florin No,genid不带参数,它在每次调用时根据任意序列和随机生成器生成一个唯一的值。这就是为什么我希望对mytable的每一行调用它一次。看起来答案中已经有了一个有效的解决方案,但是为完整的
genid
+定义一个行级触发器(在插入/更新该列时更新a、b和c)是一个选项吗?附加列不是一个选项,我们有大约2000个这样的表,模式是相当稳定的。此列对于数百万条记录来说开销太大。与我冗长的解决方案相比,这可能是阻力最小的路径。。。(如果在这种情况下允许使用pgplsql)在这种情况下,整个表更新只调用一次
genid()
,对吗?我需要为每一行调用一次。是的,整个表更新只调用一次。在您的情况下,我认为用户Lukas建议了实现这一点的最合适的方法。这对PostgreSQL不起作用(您不能声明这样的变量),这非常有效,谢谢。不过,我有一些性能问题,因为这涉及到散列连接。第二个
是多余的,其中package_id=10
。子查询已经进行了筛选(应该如此)。如果
mytable.id
被编入索引(它应该是这样的),冗余检查就没有用了。@Cezariusz:您分析过执行计划了吗?如果您在主键上进行自联接,则联接应该相当有效。@ErwinBrandstetter:您是对的。我没有那样想过。现在我来修正+1,我喜欢你的答案。:)您可能应该链接到8.4版(OP的版本)或当前版本的手册。最好是
/interactive
分支。不适用于任何版本的PostgreSQL,也称为“错误答案”。