在PL / pgSQL中更新整行

时间:2012-09-21 10:42:21

标签: postgresql sql-update plpgsql

我有plpgsql函数:

CREATE OR REPLACE FUNCTION test() RETURNS VOID AS
$$
DECLARE
    my_row my_table%ROWTYPE;
BEGIN
    SELECT * INTO my_row FROM my_table WHERE id='1';
    my_row.date := now();
END;
$$ LANGUAGE plpgsql;

我想知道是否可以直接更新my_row记录。

我现在发现的唯一方法是:

UPDATE my_table SET date=now() WHERE id='1';

请注意,这只是一个示例函数,真正的函数远比这复杂。

我正在使用PostgreSQL 9.2。

更新:

对于这种困惑感到抱歉,我想说的是:

SELECT * INTO my_row FROM my_table INTO my_row WHERE id='1';
make_lots_of_complicated_modifications_to(my_row, other_complex_parameters);
UPDATE my_row;

即。使用我的_ row来保存基础表中的信息。我有很多参数需要更新。

3 个答案:

答案 0 :(得分:4)

  

我想知道是否可以直接更新“my_row”   记录。

是的 您可以在plpgsql中更新行或记录类型的列 - 就像您拥有它一样。它应该工作,显然?

这会更新基础表,当然不是变量!

UPDATE my_table SET date=now() WHERE id='1';

你在这里混淆了两件事......


回答评论中的澄清

我不认为PostgreSQL中的语法可以UPDATE整行。不过你可以UPDATE a column list。考虑一下这个演示:

请注意我使用thedate代替date作为列名,date在每个SQL标准中都是reserved word,在PostgreSQL中是类型名称。

CREATE TEMP TABLE my_table (id serial, thedate date);
INSERT INTO my_table(thedate) VALUES (now());

CREATE OR REPLACE FUNCTION test_up()
  RETURNS void LANGUAGE plpgsql AS
$func$
DECLARE
    _r my_table;
BEGIN
   SELECT * INTO _r FROM my_table WHERE id = 1;
   _r.thedate := now()::date + 5 ;

   UPDATE my_table t
    -- explicit list of columns to be to updated
   SET   (id, thedate) = (_r.id, _r.thedate)
   WHERE  t.id = 1;
END
$func$;

SELECT test_up();
SELECT * FROM my_table;

但是,您可以轻松地 INSERT a whole row 。只是不提供表的列列表(通常应该这样,但在这种情况下,它完全没问题,而不是)。

由于UPDATE内部是DELETE,后跟INSERT,并且函数会自动封装事务中的所有内容,我看不出,为什么你不能使用相反:

CREATE OR REPLACE FUNCTION x.test_ delins()
  RETURNS void LANGUAGE plpgsql AS
$func$
DECLARE
    _r my_table;
BEGIN
   SELECT * INTO _r
   FROM my_table WHERE id = 1;
   _r.thedate := now()::date + 10;

   DELETE FROM my_table t WHERE t.id = 1;
   INSERT INTO my_table SELECT _r.*;
END
$func$;

答案 1 :(得分:0)

是的,它可以更新/附加行型变量

CREATE OR REPLACE FUNCTION test() RETURNS VOID AS $$
DECLARE    
         my_row my_table%ROWTYPE;
BEGIN
         SELECT * INTO my_row FROM my_table WHERE id='1';
         my_row.date := now(); 
         raise notice  'date  : %; ',my_row.date;
END;
$$ LANGUAGE plpgsql;

此处加注通知仅显示今天的日期。

但这不会更新my_table中的列日期。

答案 2 :(得分:0)

我设法通过两行代码使它在PLPGSQL中工作。

给定一个名为table的模式中名为example的表以及一个声明为_record的相同类型的记录,您可以更新表中的所有列以匹配该记录使用以下技巧:

declare _record example.table;

...

-- get the columns in the correct order, as a string
select string_agg(format('%I', column_name), ',' order by ordinal_position)
  into _columns
  from information_schema.columns
  where table_schema='example' and table_name='table';

execute 'update example.table set (' || _columns || ') = row($1.*) where pkey=$2'
  using _record, _record.pkey;

在上面的示例中,当然,_record.pkey是表的主键。