Skip to content

Instantly share code, notes, and snippets.

@Charmatzis
Created April 2, 2024 06:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Charmatzis/5b15fbff79cfa350b930a4fde61b2b0c to your computer and use it in GitHub Desktop.
Save Charmatzis/5b15fbff79cfa350b930a4fde61b2b0c to your computer and use it in GitHub Desktop.
Fix PKs seqs in public schema in Postgres
CREATE OR REPLACE FUNCTION primary_id_sequences_from_all_tables()
RETURNS TABLE (table_name TEXT, column_name TEXT, data_type TEXT, max BIGINT, next BIGINT) AS $$
DECLARE
rec RECORD;
BEGIN
FOR rec IN
SELECT tc.table_name, kcu.column_name, c.data_type
FROM information_schema.table_constraints AS tc
JOIN information_schema.key_column_usage AS kcu
ON tc.constraint_name = kcu.constraint_name
AND tc.table_schema = kcu.table_schema
AND tc.table_schema IN ('public')
JOIN information_schema.columns AS c
ON kcu.table_name = c.table_name
AND kcu.column_name = c.column_name
AND c.data_type IN ('smallint', 'integer', 'bigint', 'decimal', 'numeric', 'real', 'double precision')
WHERE tc.constraint_type = 'PRIMARY KEY'
LOOP
RETURN QUERY EXECUTE 'SELECT ' || quote_nullable(rec.table_name) || ', ' || quote_nullable(rec.column_name) || ', ' || quote_nullable(rec.data_type) || ', (SELECT COALESCE(MAX(' || rec.column_name || '), 0)::BIGINT FROM ' || rec.table_name || '), (SELECT nextval(pg_get_serial_sequence(' || quote_nullable(rec.table_name) || ', ' || quote_nullable(rec.column_name) || ')))';
END LOOP;
END;
$$ LANGUAGE plpgsql;
SELECT table_name, column_name, data_type, max, next, (max - next) AS diff
FROM primary_id_sequences_from_all_tables()
WHERE next IS NOT NULL AND max > next
ORDER BY diff DESC;
CREATE OR REPLACE FUNCTION fixup_primary_id_sequences_in_all_tables()
RETURNS TABLE (table_name TEXT, column_name TEXT, max BIGINT, next BIGINT, set_to BIGINT) AS $$
DECLARE
rec RECORD;
BEGIN
FOR rec IN
SELECT seqs.table_name, seqs.column_name, seqs.max, seqs.next
FROM primary_id_sequences_from_all_tables() AS seqs
WHERE seqs.next IS NOT NULL AND seqs.max > seqs.next
LOOP
RETURN QUERY EXECUTE 'SELECT ' || quote_nullable(rec.table_name) || ', ' || quote_nullable(rec.column_name) || ', ' || rec.max || '::BIGINT, ' || rec.next || '::BIGINT, setval(pg_get_serial_sequence(' || quote_nullable(rec.table_name) || ', ' || quote_nullable(rec.column_name) || '), (SELECT MAX(' || rec.column_name || ') FROM ' || rec.table_name || ')+1) AS set_to';
END LOOP;
END;
$$ LANGUAGE plpgsql;
SELECT * FROM fixup_primary_id_sequences_in_all_tables();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment