PostgreSQL 用一个查询增加一个表的序列

Posted

技术标签:

【中文标题】PostgreSQL 用一个查询增加一个表的序列【英文标题】:PostgreSQL increase a table's sequence with one query 【发布时间】:2014-09-05 12:29:46 【问题描述】:

我想将以下两个查询合二为一:

SELECT pg_get_serial_sequence('purchase_orders', 'id');
SELECT setval('purchase_orders_id_seq', 30000);

但如果我将上面的 SELECT 放入 setval 的第一个参数中,我会得到:

SELECT setval(SELECT pg_get_serial_sequence('purchase_orders', 'id'), 30000);

ERROR: syntax error at or near "SELECT"
SQL state: 42601
Character: 15

如何将选择的结果(“purchase_orders_id_seq”)传递给 setval?

编辑:这样做的原因是;我想将它用作一个功能,用户只需输入表的名称和一个数字即可设置序列。

FUNCTION set_id_sequence(TEXT table_name, INTEGER sequence);

【问题讨论】:

编辑您的问题并添加失败的查询。 什么是pg_serial_get_sequence?我从来没有听说过它,当被\df pg_get_serial_sequence 询问时,我的 9.4 安装表示无知。你想在这里完成/修复什么,你想解决什么问题? 我编辑了这个问题,现在可能更清楚了。 不,不是。为什么你首先需要这样做?您不需要到处设置序列。 这不是我需要的。 :) 我们的客户有一个系统管理员,他要求他可以通过让它们的 id 从 1 开始和用户创建的条目(假设为 10000)来分隔默认数据。 【参考方案1】:

一般功能和自动化

所有“迁移”或“启动数据库”SQL 脚本文件在使用serial 自动化之前都有一些受控的INSERT 序列,因此需要一个简单的命令说“ok,回到标准操作”。

这个通用操作是SELECT MAX(id)+1 FROM schemaName.tableName... 而且,正如上面的@NickBarnes 所示,基本的setval() 操作是setval(pg_get_serial_sequence('schemaName.tableName', 'idName'), NEWVAL),因此我们将所有这些放在一起自动完成任务。

2018年标准化提案

CREATE FUNCTION std_setmaxval(
    p_tname text,
    p_id_name text DEFAULT 'id'
) RETURNS SETOF bigint AS $f$
BEGIN 
RETURN QUERY EXECUTE  format(
    'SELECT setval(pg_get_serial_sequence(%L,%L), COALESCE((SELECT MAX(%s)+1 FROM %s), 1) , false)'
     ,p_tname, p_id_name, p_id_name, p_tname
    );
END
$f$ LANGUAGE PLpgSQL;

请参阅quotation problem/solution 进行优化。 请查看此答案,它是一个 Wiki (!)。并更新standard snippet proposal。


PS:我不明白为什么 postgreSQL 不为此任务提供本机函数...好吧,我没有看到 info's Guide 或 sequence's Guide。

【讨论】:

【参考方案2】:

如果要将子查询结果作为函数参数传递,则需要将其括起来:

SELECT setval((SELECT pg_get_serial_sequence('purchase_orders', 'id')), 30000);

但在这种情况下,SELECT 是多余的;您可以直接调用该函数:

SELECT setval(pg_get_serial_sequence('purchase_orders', 'id'), 30000);

【讨论】:

是的!而已!非常感谢,这是一个多余的选择。 :-)【参考方案3】:

更改序列所有者:

ALTER SEQUENCE purchase_orders_id_seq OWNED BY purchase_orders.id;

设置序列值:

SELECT pg_catalog.setval('purchase_orders_id_seq', 30000, true);
ALTER TABLE ONLY purchase_orders ALTER COLUMN id SET DEFAULT
    nextval('purchase_orders_id_seq'::regclass);

【讨论】:

快到了!但是 SET DEFAULT 不接受 ::regclass 的 pg_get_serial_sequence('purchase_orders', 'id')。所以谁想修改purchase_orders 表还是要知道'purchase_orders_id_seq' 标识符。我脑子里想的是一个函数,比如:set_id_sequence(TEXT table_name, INTEGER sequence)。因此,调用此函数的人只需知道表的名称。

以上是关于PostgreSQL 用一个查询增加一个表的序列的主要内容,如果未能解决你的问题,请参考以下文章

如何在Postgresql中创建序列数并应用在数据表

如何在Postgresql中创建序列数并应用在数据表

如何给oracle中的表建一个序列

PostgreSQL PG序列 与 序列是否可以绑定到多个表的疑问

postgreSQL怎样创建一个序列号/自动递增的字段

从大表的子集中对随机行进行最快查询 - postgresql