我想选择数据库中的所有序列,获取序列模式,相关表,表模式,相关列。
我尝试了以下查询:
SELECT
ns.nspname AS sequence_schema_name,
s.relname AS sequence_name,
t_ns.nspname AS table_schema_name,
t.relname AS table_name,
a.attname AS column_name,
s.oid,
s.relnamespace,
d.*,
a.*
FROM pg_class s
JOIN pg_namespace ns
ON ns.oid = s.relnamespace
left JOIN pg_depend d --
ON d.objid = s.oid --TO FIX???
AND d.classid = 'pg_class'::regclass --TO FIX???
AND d.refclassid = 'pg_class'::regclass --TO FIX???
left JOIN pg_class t
ON t.oid = d.refobjid --TO FIX???
left JOIN pg_attribute a
ON a.attrelid = d.refobjid
AND a.attnum = d.refobjsubid
left JOIN pg_namespace t_ns
ON t.relnamespace = t_ns.oid
WHERE s.relkind = 'S'
;
很遗憾,此查询无法100%正常工作。该查询会过滤一些序列。
我需要它进行进一步处理(在不同的ENV上恢复数据后,我需要找到最大列值并将序列设置为MAX + 1)。
有人可以帮助我吗?
答案 0 :(得分:1)
以下查询应起作用:
create table foo(id serial, v integer);
create table boo(id_boo serial, v integer);
create sequence omega;
create table bubu(id integer default nextval('omega'), v integer);
select sn.nspname as seq_schema,
s.relname as seqname,
st.nspname as tableschema,
t.relname as tablename,
at.attname as columname
from pg_class s
join pg_namespace sn on sn.oid = s.relnamespace
join pg_depend d on d.refobjid = s.oid
join pg_attrdef a on d.objid = a.oid
join pg_attribute at on at.attrelid = a.adrelid and at.attnum = a.adnum
join pg_class t on t.oid = a.adrelid
join pg_namespace st on st.oid = t.relnamespace
where s.relkind = 'S'
and d.classid = 'pg_attrdef'::regclass
and d.refclassid = 'pg_class'::regclass;
┌────────────┬────────────────┬─────────────┬───────────┬───────────┐
│ seq_schema │ seqname │ tableschema │ tablename │ columname │
╞════════════╪════════════════╪═════════════╪═══════════╪═══════════╡
│ public │ foo_id_seq │ public │ foo │ id │
│ public │ boo_id_boo_seq │ public │ boo │ id_boo │
│ public │ omega │ public │ bubu │ id │
└────────────┴────────────────┴─────────────┴───────────┴───────────┘
(3 rows)
要调用与序列相关的功能,可以使用s.oid
列。对于这种情况,它是序列唯一的oid标识符。您需要将其强制转换为regclass
。
您请求的脚本如下所示:
do $$
declare
r record;
max_val bigint;
begin
for r in
select s.oid as seqoid,
at.attname as colname,
a.adrelid as reloid
from pg_class s
join pg_namespace sn on sn.oid = s.relnamespace
join pg_depend d on d.refobjid = s.oid
join pg_attrdef a on d.objid = a.oid
join pg_attribute at on at.attrelid = a.adrelid and at.attnum = a.adnum
where s.relkind = 'S'
and d.classid = 'pg_attrdef'::regclass
and d.refclassid = 'pg_class'::regclass
loop
-- probably lock here can be safer, in safe (single user) maintainance mode
-- it is not necessary
execute format('lock table %s in exclusive mode', r.reloid::regclass);
-- expect usual one sequnce per table
execute format('select max(%I) from %s', r.colname, r.reloid::regclass)
into max_val;
-- set sequence
perform setval(r.seqoid, max_val + 1);
end loop;
end;
$$
注意:在%s
函数中为表名或序列名使用format
是安全的,因为从Oid
类型到regclass
类型的转换会生成安全字符串(模式为在每次需要时使用,转义在每次需要时使用。)