Ці функції загрожують небезпеками, коли назви послідовностей, назви стовпців, назви таблиць або назви схем мають забавні символи, такі як пробіли, розділові знаки тощо. Я написав це:
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';
Використовуючи іншу якість, ви можете скинути лише послідовність у певній схемі тощо. Наприклад, якщо ви хочете відрегулювати послідовності в схемі "public":
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 () у цьому замовчуванні має: :: текст, доданий до складу :: regclass Я думаю, що це пов'язано з тим, що бази даних pg_dump'ed від старих версій PostgreSQL. Що станеться, що функція послідовності_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)
Як тільки ви виправили це, функція працює правильно для цієї таблиці, а також для всіх інших, які можуть використовувати ту саму послідовність.