【问题标题】:Select multiple ids from a PostgreSQL sequence从 PostgreSQL 序列中选择多个 id
【发布时间】:2010-10-28 03:10:05
【问题描述】:

是否有一种简洁的方法可以在 1 个查询中多次选择 PostgreSQL 序列的 nextval?这将是唯一返回的值。

例如,我想做一些非常简短而甜蜜的事情,例如:

SELECT NEXTVAL('mytable_seq', 3) AS id;

得到:

 id  
-----
 118
 119
 120
(3 rows)

【问题讨论】:

    标签: postgresql select nextval


    【解决方案1】:
    select nextval('mytable_seq') from generate_series(1,3);
    

    generate_series 是一个函数,它返回许多带有序列号的行,由它的参数配置。

    在上面的例子中,我们不关心每一行的值,我们只是使用 generate_series 作为行生成器。对于每一行,我们都可以调用 nextval。在这种情况下,它返回 3 个数字(nextvals)。

    您可以将其包装到函数中,但考虑到查询有多短,我不确定这是否真的明智。

    【讨论】:

    • 请注意,这 3 个数字(nextvals)不保证是连续的。
    【解决方案2】:

    关于这个确切的问题有一篇很棒的文章:“getting multiple values from sequences”。

    如果性能不是问题,例如当使用序列值时,获取它们的时间会相形见绌,或者 n 很小,那么 SELECT nextval('seq') FROM generate_series (1,n) 方法是最简单和最合适的。

    但是在为批量加载准备数据时,文章中的最后一种方法是从锁中将序列增加 n 是合适的。

    【讨论】:

    • 有趣的是,那篇文章似乎是由写我接受的答案的人写的 :-) 不管怎样,generate_series 符合我的需要,因为我需要的 id 数量大约是十几个。在一个非常罕见的情况下,可能是 100 ......所以文章中提出的其他解决方案的失败对我来说太陡峭了。为不错的链接 +1!
    【解决方案3】:

    除非您真的想要返回三行,否则我会将每个选择的序列设置为“INCREMENT BY 3”。然后你可以简单地将 1 和 2 添加到结果中,得到你的三个序列号。

    我尝试添加指向 postgresql 文档的链接,但显然我不允许发布链接。

    【讨论】:

    • 赞赏,但来自 Ants Aasma 的链接中指出的缺点太陡峭,我无法更改增量......而且我需要的 id 数量各不相同,所以我更喜欢单独获取所有 id (这使得使用 id 的代码更简单)。
    【解决方案4】:
    
    CREATE OR REPLACE FUNCTION foo() RETURNS SETOF INT AS $$
    DECLARE
        seqval int; x int;
    BEGIN
    x := 0;
    
    WHILE x < 100 LOOP
        SELECT into seqval nextval('f_id_seq');
        RETURN NEXT seqval;
        x := x+1;
    END LOOP;
    RETURN;
    END;
    $$ LANGUAGE plpgsql STRICT;
    

    当然,如果您只是想推进序列,这里有setval()

    您还可以让函数获取循环次数的参数:

    CREATE OR REPLACE FUNCTION foo(loopcnt int) RETURNS SETOF INT AS $$
    DECLARE
        seqval int;       
        x int;
    BEGIN
    x := 0;
    WHILE x < loopcnt LOOP
        SELECT into seqval nextval('f_id_seq');
        RETURN NEXT seqval;x := x+1;
    END LOOP;
    RETURN;
    END;
    $$ LANGUAGE plpgsql STRICT;
    

    【讨论】:

    • 请注意,由于使用了 'setof',您必须将其称为表:select * from foo(500);
    【解决方案5】:

    我目前最好的解决方案是:

    SELECT NEXTVAL('mytable_seq') AS id
    UNION ALL
    SELECT NEXTVAL('mytable_seq') AS id
    UNION ALL
    SELECT NEXTVAL('mytable_seq') AS id;
    

    这将正确返回 3 行...但我想要一些最小的 SQL,即使是 100 或更多的 NEXTVAL 调用。

    【讨论】:

      猜你喜欢
      • 2013-05-31
      • 2014-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多