如何在PostgreSQL中更新内部的源表以进行循环主体

发布于 2025-02-13 00:49:42 字数 1048 浏览 0 评论 0 原文

我有一个表格,我要迭代循环,并且在试图更新for循环中的源表数据时,它没有反映。在下面的示例中,我希望Rasie通知语句应执行5次,但仅执行3次。

DO $$
DECLARE p_Id int;

BEGIN
    DROP TABLE IF EXISTS TempTbl;
    CREATE TEMPORARY TABLE TempTbl (Id int);
    INSERT INTO TempTbl VALUES (1);
    INSERT INTO TempTbl VALUES (2);
    INSERT INTO TempTbl VALUES (3);    
        
    FOR p_Id in SELECT * FROM TempTbl
    LOOP        
        RAISE NOTICE 'Value of p_Id: %', p_Id;

        INSERT INTO TempTbl
        SELECT 4
        WHERE 4 NOT IN (SELECT Id FROM TempTbl);
        
        INSERT INTO TempTbl
        SELECT 5
        WHERE 5 NOT IN (SELECT Id FROM TempTbl);      
    END LOOP;
    
END $$;

当前输出

NOTICE:  Value of p_Id: 1
NOTICE:  Value of p_Id: 2
NOTICE:  Value of p_Id: 3
 

预期输出

NOTICE:  Value of p_Id: 1
NOTICE:  Value of p_Id: 2
NOTICE:  Value of p_Id: 3
NOTICE:  Value of p_Id: 4
NOTICE:  Value of p_Id: 5

注意:我将从前3行中检索值4和5(即,我无法插入全部开始时的值)。

I have a table through which I'm iterating a for loop and while trying to update the source table data inside the for loop, it's not reflecting. In the below example I want the RASIE NOTICE statement should execute 5 times but it's only executing 3 times.

DO $
DECLARE p_Id int;

BEGIN
    DROP TABLE IF EXISTS TempTbl;
    CREATE TEMPORARY TABLE TempTbl (Id int);
    INSERT INTO TempTbl VALUES (1);
    INSERT INTO TempTbl VALUES (2);
    INSERT INTO TempTbl VALUES (3);    
        
    FOR p_Id in SELECT * FROM TempTbl
    LOOP        
        RAISE NOTICE 'Value of p_Id: %', p_Id;

        INSERT INTO TempTbl
        SELECT 4
        WHERE 4 NOT IN (SELECT Id FROM TempTbl);
        
        INSERT INTO TempTbl
        SELECT 5
        WHERE 5 NOT IN (SELECT Id FROM TempTbl);      
    END LOOP;
    
END $;

Current Output

NOTICE:  Value of p_Id: 1
NOTICE:  Value of p_Id: 2
NOTICE:  Value of p_Id: 3
 

Expected Output

NOTICE:  Value of p_Id: 1
NOTICE:  Value of p_Id: 2
NOTICE:  Value of p_Id: 3
NOTICE:  Value of p_Id: 4
NOTICE:  Value of p_Id: 5

Note: I would be retrieving the values 4 and 5 from the first 3 rows (i.e., I can't insert all the values at the beginning).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

萌辣 2025-02-20 00:49:43

循环似乎是基于误解。无论哪种方式,这都是它的工作方式:

DO
$do$
DECLARE
   p_id int;
   val4 int;
   val5 int;
BEGIN
   DROP TABLE IF EXISTS pg_temp.tbl;
   CREATE TEMPORARY TABLE tbl (id int PRIMARY KEY);
   INSERT INTO tbl VALUES (1), (2), (3);    

   FOR p_id IN
      SELECT * FROM tbl
   LOOP        
      RAISE NOTICE 'Value of p_id: %', p_id;
      -- compute values val4 & val5
      -- which, oddly, seems to require a loop?
      -- I doubt that
   END LOOP;

   -- this somehow happens in the loop
   val4 := 4;
   val5 := 5;

   INSERT INTO tbl VALUES (val4) ON CONFLICT DO NOTHING;
   IF FOUND THEN
      RAISE NOTICE 'Value of p_id: %', val4;
   ELSE
      RAISE NOTICE 'Value of p_id: % (failed with unique violation)', val4;
   END IF;

   INSERT INTO tbl VALUES (val5) ON CONFLICT DO NOTHING;
   IF FOUND THEN
      RAISE NOTICE 'Value of p_id: %', val5;
   ELSE
      RAISE NOTICE 'Value of p_id: % (failed with unique violation)', val5;
   END IF;
END
$do$;

避免不在(选择...)中,除非您确切知道自己在做什么。请参阅:

并避免使用骆驼标识符。请参阅:

The loop seems to be based on a misunderstanding. Either way, this is how it could work:

DO
$do$
DECLARE
   p_id int;
   val4 int;
   val5 int;
BEGIN
   DROP TABLE IF EXISTS pg_temp.tbl;
   CREATE TEMPORARY TABLE tbl (id int PRIMARY KEY);
   INSERT INTO tbl VALUES (1), (2), (3);    

   FOR p_id IN
      SELECT * FROM tbl
   LOOP        
      RAISE NOTICE 'Value of p_id: %', p_id;
      -- compute values val4 & val5
      -- which, oddly, seems to require a loop?
      -- I doubt that
   END LOOP;

   -- this somehow happens in the loop
   val4 := 4;
   val5 := 5;

   INSERT INTO tbl VALUES (val4) ON CONFLICT DO NOTHING;
   IF FOUND THEN
      RAISE NOTICE 'Value of p_id: %', val4;
   ELSE
      RAISE NOTICE 'Value of p_id: % (failed with unique violation)', val4;
   END IF;

   INSERT INTO tbl VALUES (val5) ON CONFLICT DO NOTHING;
   IF FOUND THEN
      RAISE NOTICE 'Value of p_id: %', val5;
   ELSE
      RAISE NOTICE 'Value of p_id: % (failed with unique violation)', val5;
   END IF;
END
$do$;

Avoid NOT IN (SELECT ...) unless you know exactly what you are doing. See:

And avoid CaMeL-case identifiers. See:

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文