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 用一个查询增加一个表的序列的主要内容,如果未能解决你的问题,请参考以下文章