Эти функции сопряжены с опасностями, когда имена последовательностей, имен столбцов, имен таблиц или схем имеют смешные символы, такие как пробелы, знаки пунктуации и тому подобное. Я написал это:
CREATE OR REPLACE FUNCTION sequence_max_value(oid) RETURNS bigint
VOLATILE STRICT LANGUAGE plpgsql AS $$
DECLARE
tabrelid oid;
colname name;
r record;
newmax bigint;
BEGIN
FOR tabrelid, colname IN SELECT attrelid, attname
FROM pg_attribute
WHERE (attrelid, attnum) IN (
SELECT adrelid::regclass,adnum
FROM pg_attrdef
WHERE oid IN (SELECT objid
FROM pg_depend
WHERE refobjid = $1
AND classid = 'pg_attrdef'::regclass
)
) LOOP
FOR r IN EXECUTE 'SELECT max(' || quote_ident(colname) || ') FROM ' || tabrelid::regclass LOOP
IF newmax IS NULL OR r.max > newmax THEN
newmax := r.max;
END IF;
END LOOP;
END LOOP;
RETURN newmax;
END; $$ ;
Вы можете вызвать его для одной последовательности, передав ему OID, и он вернет наибольший номер, используемый любой таблицей, в которой последовательность по умолчанию установлена; или вы можете запустить его с таким запросом, чтобы сбросить все последовательности в вашей базе данных:
select relname, setval(oid, sequence_max_value(oid))
from pg_class
where relkind = 'S';
Используя другую квалификацию, вы можете сбросить только последовательность в определенной схеме и т. Д. Например, если вы хотите настроить последовательности в «публичной» схеме:
select relname, setval(pg_class.oid, sequence_max_value(pg_class.oid))
from pg_class, pg_namespace
where pg_class.relnamespace = pg_namespace.oid and
nspname = 'public' and
relkind = 'S';
Обратите внимание, что из-за того, как работает setval (), вам не нужно добавлять 1 к результату.
В качестве заключительного замечания я должен предупредить, что некоторые базы данных, по-видимому, имеют значения по умолчанию, связанные с последовательностями, которые не позволяют системным каталогам иметь полную информацию о них. Это происходит, когда вы видите такие вещи в psql's \ d:
alvherre=# \d baz
Tabla «public.baz»
Columna | Tipo | Modificadores
---------+---------+------------------------------------------------
a | integer | default nextval(('foo_a_seq'::text)::regclass)
Обратите внимание, что вызов nextval () в этом предложении по умолчанию имеет приведение :: text в дополнение к приведению :: regclass. Я думаю это связано с тем, что базы данных были pg_dump'ом из старых версий PostgreSQL. Что произойдет, так это то, что функция sequence_max_value (), приведенная выше, будет игнорировать такую таблицу. Чтобы устранить проблему, вы можете переопределить предложение DEFAULT, чтобы ссылаться на последовательность напрямую без приведения:
alvherre=# alter table baz alter a set default nextval('foo_a_seq');
ALTER TABLE
Тогда psql отобразит это правильно:
alvherre=# \d baz
Tabla «public.baz»
Columna | Tipo | Modificadores
---------+---------+----------------------------------------
a | integer | default nextval('foo_a_seq'::regclass)
Как только вы исправите это, функция будет работать правильно для этой таблицы, а также для всех других, которые могут использовать ту же последовательность.