【问题标题】:UPDATE a whole row in PL/pgSQL更新 PL/pgSQL 中的一整行
【发布时间】:2012-09-13 18:50:11
【问题描述】:

我有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;

即使用 my_row 将信息持久保存在基础表中。我有很多参数要更新。

【问题讨论】:

  • 你为什么不首先选择 NOW() 而不是模糊的 * ?
  • 您要更新 plpgsql 函数中的变量还是基础表中的行?
  • 我想将变量持久化到表中,而不必重写逐字段查询。

标签: postgresql sql-update plpgsql


【解决方案1】:

我想知道是否可以直接更新“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$;

【讨论】:

  • 我怎样才能直接持久化 ROWTYPE 变量?
  • 你想UPDATE整行还是一列?
  • 整行,我正在更改许多具有复杂计算的字段。它类似于 oracle 的 SET ROW。
  • Erwin... 删除/插入方法的问题似乎是外键问题。您将/如何解决这些问题?
  • @DavidS:指向表的外键将禁止 DELETE/INSERT 解决方法。您可以使用动态 SQL 从系统目录中为 UPDATE 生成一长列列列表,特别是 pg_attribute ...
【解决方案2】:

我设法通过几行代码在 PLPGSQL 中实现了这个功能。

给定名为example 的架构中名为table 的表,以及声明为_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当然是表的主键。

【讨论】:

    【解决方案3】:

    Postgresql 没有在更新中设置行。 如果您不更新整行,则应分别为每一列分配值

    【讨论】:

      【解决方案4】:

      是的,可以更新/追加行类型变量,

      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 中的列日期。

      【讨论】:

      • 我知道,日期就是一个例子,我正在对 my_row 进行大量更改,我想要一种简单的方法来再次保存信息,而无需编写 UPDATE my_table SET WHERE id=my_row.id。我认为 Oracle 有一个 SET ROW 系统来保存具有这些结构的记录。
      猜你喜欢
      • 2021-12-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-27
      • 2017-05-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多