最近一个项目更换了数据库,从原有数据库中导入了一些数据,然而PostgreSql新数据库中的主键序列仍然为1,若直接插入新数据会产生报错,一个个设置每个表的主键序列值到最大太麻烦了,研究了一下使用了游标来实现自动完成所有表的序列更新。下列代码会创建一个update_tables_seq函数,若使用之后不再需要可以删除。
PLSQL
CREATE OR REPLACE FUNCTION update_tables_seq ( )
RETURNS void AS $$
DECLARE
seq_name_cursor CURSOR FOR
SELECT a.attname AS column_name, c.relname AS table_name, s.relname AS seq_name
FROM pg_class c
JOIN pg_depend d ON d.refobjid = c.oid
JOIN pg_class s ON d.objid = s.oid
JOIN pg_namespace n ON s.relnamespace = n.oid
JOIN pg_attribute a ON a.attrelid = c.oid AND a.attnum = d.refobjsubid
WHERE d.classid = 'pg_class'::regclass
AND d.refclassid = 'pg_class'::regclass
AND s.relkind = 'S'
AND n.nspname = 'public'; -- 替换为序列所在的 schema 名称
prepared_sql VARCHAR(255);
BEGIN
FOR ref_record in seq_name_cursor LOOP
prepared_sql := 'SELECT setval( ''' || ref_record.seq_name;
prepared_sql := prepared_sql || ''','||'( SELECT MAX ( ' || ref_record.column_name || ' ) FROM "'||ref_record.table_name||'") );';
RAISE NOTICE '%', prepared_sql;
EXECUTE prepared_sql;
END LOOP;
END;
$$ LANGUAGE plpgsql;
执行完以上代码后,再执行以下代码调用即可:
PLSQL
SELECT update_tables_seq();