【问题标题】:How to create a stored procedure in POSTGRESQL that makes a FOR loop?如何在 POSTGRESQL 中创建一个生成 FOR 循环的存储过程?
【发布时间】:2021-12-31 03:20:26
【问题描述】:

我正在研究如何在 POSTGRESQL 中创建触发器和存储过程,我的任务是更新 ALBUM 表中名为 num_long_title_songs 的列。

需要统计一个名为songs的表中超过12个字符的歌曲的数量,然后更新ALBUM中该列的值。

我用 for 循环创建了下一个查询,这正是我想要的:

do $$
begin
    FOR i IN 1..100 LOOP
    UPDATE ALBUM
    SET  num_long_title_songs =(SELECT count(s.title)
                                FROM ALBUM a,SONG s
                                WHERE a.id_album=s.id_album
                                AND LENGTH(s.title) > 12
                                AND a.id_album=i
                                GROUP BY a.id_album
                                ORDER BY a.id_album)
    WHERE id_album IN (SELECT a.id_album
                                FROM ALBUM a,SONG s
                                WHERE a.id_album=s.id_album
                                AND LENGTH(s.title) > 12
                                AND a.id_album=i
                                GROUP BY a.id_album
                                ORDER BY a.id_album);
    -- i will take on the values 1,2,3,4,5,6,7,8,9,10 within the loop
    END LOOP;
END; $$

问题是我需要创建一个存储过程才能触发。我尝试将它放在 CREATE FUNCTION 结构中,但我无法创建它...你能帮我了解如何将这个“for”循环放在函数中吗?

【问题讨论】:

  • 你不需要循环。你不需要一个函数。你不需要触发器。 [你应该使用JOIN 语法]
  • 请使用现代连接语法,而不是 1989 年以逗号分隔的表列表。
  • @wildplasser 我确实需要一个触发器和一个函数,但对于接下来的步骤,我认为我无法正确解释该练习。我想知道如何将 for 放在函数中,以便稍后在触发器中使用它:c 感谢有关 Join 的建议,我会检查它:D
  • @TheImpaler 我将使用它们:D 谢谢

标签: sql postgresql for-loop stored-procedures triggers


【解决方案1】:

如果要更新表 ALBUM 中的现有行,只需运行以下 UPDATE 语句:

UPDATE ALBUM a
   SET num_long_title_songs = s.total
FROM ( SELECT s.id_album
            , count(s.title) AS total
         FROM SONG s
        WHERE LENGTH(s.title) > 12
        GROUP BY s.id_album
     ) AS s
WHERE a.id_album=s.id_album
  AND a.num_long_title_songs <> s.total ;

如果要在表SONG 中插入或更新行时自动更新表ALBUMnum_long_title_songs 字段,则需要trigger function

CREATE OR REPLACE FUNCTION update_num_long_title_songs ()
RETURNS TRIGGER LANGUAGE plpgsql AS
$$
BEGIN
    UPDATE ALBUM a
       SET num_long_title_songs = s.total
    FROM ( SELECT s.id_album
                , count(s.title) AS total
             FROM SONG s
            WHERE LENGTH(s.title) > 12
              AND s.id_album = NEW.id_album
         ) AS s
    WHERE a.id_album=s.id_album
      AND a.num_long_title_songs <> s.total ;
END ;
$$ ;
    
CREATE TRIGGER after_insert_update_SONG AFTER INSERT OR UPDATE OF title ON SONG
FOR EACH ROW EXECUTE FUNCTION update_num_long_title_songs () ;

AFTER 很重要,以便将在表 SONG 中插入或更新的新行考虑到 num_long_title_songs 的新值。

【讨论】:

  • 当然,触发声明中的UPDATE OF title 子句是一级预防医学,而WHERE 条件绝对可以防止任何风险。答案已相应更新。
  • @EdouardH。感谢您的帮助,它非常有用。我以一种非常“python 循环”的思维方式来解决这个问题:D
猜你喜欢
  • 1970-01-01
  • 2019-08-20
  • 2023-04-10
  • 2019-08-21
  • 2021-12-08
  • 2022-01-26
  • 2016-01-14
  • 2011-09-02
  • 1970-01-01
相关资源
最近更新 更多