Как сбросить последовательность первичных ключей postgres, когда она выходит из синхронизации?

Я столкнулся с проблемой, что моя последовательность первичного ключа не синхронизирована с моими строками таблицы.

то есть, когда я вставляю новую строку, я получаю ошибку дубликата ключа, потому что последовательность, подразумеваемая в последовательном типе данных, возвращает число, которое уже существует.

кажется, это вызвано импортом / восстановлением, не поддерживающим последовательность должным образом.

25 ответов


-- Login to psql and run the following

-- What is the result?
SELECT MAX(id) FROM your_table;

-- Then run...
-- This should be higher than the last result.
SELECT nextval('your_table_id_seq');

-- If it's not higher... run this set the sequence last to your highest id. 
-- (wise to run a quick pg_dump first...)

BEGIN;
-- protect against concurrent inserts while you update the counter
LOCK TABLE your_table IN EXCLUSIVE MODE;
-- Update the sequence
SELECT setval('your_table_id_seq', COALESCE((SELECT MAX(id)+1 FROM your_table), 1), false);
COMMIT;

Источник-Рубиновый Форум


pg_get_serial_sequence можно использовать, чтобы избежать неправильных предположений о имени последовательности. Это сбрасывает последовательность в одном кадре:

SELECT pg_catalog.setval(pg_get_serial_sequence('table_name', 'id'), (SELECT MAX(id) FROM table_name)+1);

или более лаконично:

SELECT pg_catalog.setval(pg_get_serial_sequence('table_name', 'id'), MAX(id)) FROM table_name;

однако эта форма не может правильно обрабатывать пустые таблицы, так как max (id) равен null, и вы также не можете установить 0, потому что он будет вне диапазона последовательности. Одним из обходных путей для этого является обращение к ALTER SEQUENCE синтаксис, т. е.

ALTER SEQUENCE table_name_id_seq RESTART WITH 1;
ALTER SEQUENCE table_name_id_seq RESTART; -- 8.4 or higher

но ALTER SEQUENCE в ограниченное использование, поскольку имя последовательности и значение перезапуска не могут быть выражениями.

кажется, лучшее универсальное решение-позвонить setval С false в качестве 3-го параметра, что позволяет нам указать "следующее значение для использования":

SELECT setval(pg_get_serial_sequence('t1', 'id'), coalesce(max(id),0) + 1, false) FROM t1;

это помечает все мои коробки:

  1. избегает жесткого кодирования фактического имени последовательности
  2. правильно обрабатывает пустые таблицы
  3. обрабатывает таблицы с существующими данными и не оставляет отверстие в последовательность

наконец, обратите внимание, что pg_get_serial_sequence работает только если последовательность принадлежит столбец. Это будет иметь место, если инкрементный столбец был определен как serial тип, однако, если последовательность была добавлена вручную, необходимо обеспечить ALTER SEQUENCE .. OWNED BY также выполняется.

т. е. если serial тип использовался для создания таблицы, все это должно работать:

CREATE TABLE t1 (
  id serial,
  name varchar(20)
);

SELECT pg_get_serial_sequence('t1', 'id'); -- returns 't1_id_seq'

-- reset the sequence, regardless whether table has rows or not:
SELECT setval(pg_get_serial_sequence('t1', 'id'), coalesce(max(id),0) + 1, false) FROM t1;

но если последовательности были добавлены вручную:

CREATE TABLE t2 (
  id integer NOT NULL,
  name varchar(20)
);

CREATE SEQUENCE t2_custom_id_seq
    START WITH 1
    INCREMENT BY 1
    NO MINVALUE
    NO MAXVALUE
    CACHE 1;

ALTER TABLE t2 ALTER COLUMN id SET DEFAULT nextval('t2_custom_id_seq'::regclass);

ALTER SEQUENCE t2_custom_id_seq OWNED BY t2.id; -- required for pg_get_serial_sequence

SELECT pg_get_serial_sequence('t2', 'id'); -- returns 't2_custom_id_seq'

-- reset the sequence, regardless whether table has rows or not:
SELECT setval(pg_get_serial_sequence('t2', 'id'), coalesce(max(id),0) + 1, false) FROM t1;

это сбросит все последовательности из public, не делая никаких предположений об именах таблиц или столбцов. Протестировано на версии 8.4

CREATE OR REPLACE FUNCTION "reset_sequence" (tablename text, columnname text, sequence_name text) RETURNS "pg_catalog"."void" AS 

    $body$  
      DECLARE 
      BEGIN 

      EXECUTE 'SELECT setval( ''' || sequence_name  || ''', ' || '(SELECT MAX(' || columnname || ') FROM ' || tablename || ')' || '+1)';



      END;  

    $body$  LANGUAGE 'plpgsql';


    select table_name || '_' || column_name || '_seq', reset_sequence(table_name, column_name, table_name || '_' || column_name || '_seq') from information_schema.columns where column_default like 'nextval%';

на короткий и быстрый путь:

SELECT setval('tbl_tbl_id_seq', max(tbl_id)) FROM tbl;

tbl_id являясь serial


Alter SEQUENCE_NAME перезапуск последовательности с(выберите max (id) из table_name); Не работает.

скопировано из @tardate ответ:

SELECT setval(pg_get_serial_sequence('table_name', 'id'), MAX(id)) FROM table_name;

эта команда только для изменения автоматически сгенерированного значения последовательности ключей в postgresql

ALTER SEQUENCE "your_sequence_name" RESTART WITH 0;

вместо нуля вы можете поставить любое число, из которого вы хотите перезапустить последовательность.

имя последовательности по умолчанию "TableName_FieldName_seq". Например, если имя таблицы "MyTable" и Ваше имя поле "MyID", тогда ваше имя последовательности будет "MyTable_MyID_seq".

это ответ такой же, как ответ @murugesanponappan, но есть синтаксическая ошибка в его решение. вы не можете использовать подзапрос (select max()...) на . Так что либо вы должны использовать фиксированное числовое значение, либо вам нужно использовать переменную вместо подзапроса.


сбросить все последовательности, никаких предположений об именах, за исключением того, что первичным ключом каждой таблицы является "id":

CREATE OR REPLACE FUNCTION "reset_sequence" (tablename text, columnname text)
RETURNS "pg_catalog"."void" AS
$body$
DECLARE
BEGIN
    EXECUTE 'SELECT setval( pg_get_serial_sequence(''' || tablename || ''', ''' || columnname || '''),
    (SELECT COALESCE(MAX(id)+1,1) FROM ' || tablename || '), false)';
END;
$body$  LANGUAGE 'plpgsql';

select table_name || '_' || column_name || '_seq', reset_sequence(table_name, column_name) from information_schema.columns where column_default like 'nextval%';

эти функции чреваты опасностями, когда имена последовательности, имена столбцов, имена таблиц или имена схем имеют забавные символы, такие как пробелы, знаки препинания и тому подобное. Я написал следующее:--7-->

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 = 
                                            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';

используя другой qual вы можете сбросить только последовательность в определенной схеме, и так далее. Например, если вы хотите настроить последовательности в схеме" 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 \d:

alvherre=# \d baz
                     Tabla «public.baz»
 Columna |  Tipo   |                 Modificadores                  
---------+---------+------------------------------------------------
 a       | integer | default nextval(('foo_a_seq'::text)::regclass)

обратите внимание, что вызов nextval () в этом предложении по умолчанию имеет ::text cast в дополнение к ::regclass cast. Я!--17-->думаю это связано с помощью pg_dump объед баз данных от старой версии PostgreSQL. Что произойдет, так это то, что функция sequence_max_value () выше будет игнорировать такую таблицу. Чтобы устранить проблему, можно переопределить предложение по умолчанию для ссылки на последовательность непосредственно без В ролях:

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)

как только вы исправили это, функция работает правильно для этой таблицы, а также для всех других, которые могут использовать ту же последовательность.


сбросить всю последовательность из public

CREATE OR REPLACE FUNCTION "reset_sequence" (tablename text) RETURNS "pg_catalog"."void" AS 
$body$  
  DECLARE 
  BEGIN 
  EXECUTE 'SELECT setval( ''' 
  || tablename  
  || '_id_seq'', ' 
  || '(SELECT id + 1 FROM "' 
  || tablename  
  || '" ORDER BY id DESC LIMIT 1), false)';  
  END;  
$body$  LANGUAGE 'plpgsql';

select sequence_name, reset_sequence(split_part(sequence_name, '_id_seq',1)) from information_schema.sequences
        where sequence_schema='public';

моя версия использует первую, с некоторой проверкой ошибок...

BEGIN;
CREATE OR REPLACE FUNCTION reset_sequence(_table_schema text, _tablename text, _columnname text, _sequence_name text)
RETURNS pg_catalog.void AS
$BODY$
DECLARE
BEGIN
 PERFORM 1
 FROM information_schema.sequences
 WHERE
  sequence_schema = _table_schema AND
  sequence_name = _sequence_name;
 IF FOUND THEN
  EXECUTE 'SELECT setval( ''' || _table_schema || '.' || _sequence_name  || ''', ' || '(SELECT MAX(' || _columnname || ') FROM ' || _table_schema || '.' || _tablename || ')' || '+1)';
 ELSE
  RAISE WARNING 'SEQUENCE NOT UPDATED ON %.%', _tablename, _columnname;
 END IF;
END; 
$BODY$
 LANGUAGE 'plpgsql';

SELECT reset_sequence(table_schema, table_name, column_name, table_name || '_' || column_name || '_seq')
FROM information_schema.columns
WHERE column_default LIKE 'nextval%';

DROP FUNCTION reset_sequence(_table_schema text, _tablename text, _columnname text, _sequence_name text) ;
COMMIT;

все вместе

CREATE OR REPLACE FUNCTION "reset_sequence" (tablename text) 
RETURNS "pg_catalog"."void" AS
$body$
DECLARE
BEGIN
  EXECUTE 'SELECT setval( pg_get_serial_sequence(''' || tablename || ''', ''id''),
  (SELECT COALESCE(MAX(id)+1,1) FROM ' || tablename || '), false)';
END;
$body$  LANGUAGE 'plpgsql';

исправить 'id' последовательность данной таблицы (как обычно необходимо, например, с django).


некоторые действительно хардкорные ответы здесь, я предполагаю, что это было очень плохо примерно в то время, когда это было задано, так как многие ответы отсюда не работают для версии 9.3. The документация поскольку версия 8.0 дает ответ на этот самый вопрос:

SELECT setval('serial', max(id)) FROM distributors;

кроме того, если вам нужно позаботиться о чувствительных к регистру именах последовательностей, вот как вы это делаете:

SELECT setval('"Serial"', max(id)) FROM distributors;

Я предлагаю это решение найти на postgres wiki. Он обновляет все последовательности ваших таблиц.

SELECT 'SELECT SETVAL(' ||
       quote_literal(quote_ident(PGT.schemaname) || '.' || quote_ident(S.relname)) ||
       ', COALESCE(MAX(' ||quote_ident(C.attname)|| '), 1) ) FROM ' ||
       quote_ident(PGT.schemaname)|| '.'||quote_ident(T.relname)|| ';'
FROM pg_class AS S,
     pg_depend AS D,
     pg_class AS T,
     pg_attribute AS C,
     pg_tables AS PGT
WHERE S.relkind = 'S'
    AND S.oid = D.objid
    AND D.refobjid = T.oid
    AND D.refobjid = C.attrelid
    AND D.refobjsubid = C.attnum
    AND T.relname = PGT.tablename
ORDER BY S.relname;

Как использовать (из postgres wiki):

  • сохраните это в файл, скажем ' reset.в SQL'
  • запустите файл и сохраните его вывод Таким образом, чтобы он не включал обычные заголовки, а затем запустите этот вывод. Пример:

пример:

psql -Atq -f reset.sql -o temp
psql -f temp
rm temp

Оригинальная статья (также с исправлением для владения последовательностью) здесь


раньше я еще не пробовал код : в следующем сообщении версия для sql-кода для решений Klaus и user457226 который работал на моем ПК [Postgres 8.3], с некоторыми небольшими настройками для Klaus one и моей версии для user457226.

Клаус решение :

drop function IF EXISTS rebuilt_sequences() RESTRICT;
CREATE OR REPLACE FUNCTION  rebuilt_sequences() RETURNS integer as
$body$
  DECLARE sequencedefs RECORD; c integer ;
  BEGIN
    FOR sequencedefs IN Select
      constraint_column_usage.table_name as tablename,
      constraint_column_usage.table_name as tablename, 
      constraint_column_usage.column_name as columnname,
      replace(replace(columns.column_default,'''::regclass)',''),'nextval(''','') as sequencename
      from information_schema.constraint_column_usage, information_schema.columns
      where constraint_column_usage.table_schema ='public' AND 
      columns.table_schema = 'public' AND columns.table_name=constraint_column_usage.table_name
      AND constraint_column_usage.column_name = columns.column_name
      AND columns.column_default is not null
   LOOP    
      EXECUTE 'select max('||sequencedefs.columnname||') from ' || sequencedefs.tablename INTO c;
      IF c is null THEN c = 0; END IF;
      IF c is not null THEN c = c+ 1; END IF;
      EXECUTE 'alter sequence ' || sequencedefs.sequencename ||' restart  with ' || c;
   END LOOP;

   RETURN 1; END;
$body$ LANGUAGE plpgsql;

select rebuilt_sequences();

решение user457226:

--drop function IF EXISTS reset_sequence (text,text) RESTRICT;
CREATE OR REPLACE FUNCTION "reset_sequence" (tablename text,columnname text) RETURNS bigint --"pg_catalog"."void"
AS
$body$
  DECLARE seqname character varying;
          c integer;
  BEGIN
    select tablename || '_' || columnname || '_seq' into seqname;
    EXECUTE 'SELECT max("' || columnname || '") FROM "' || tablename || '"' into c;
    if c is null then c = 0; end if;
    c = c+1; --because of substitution of setval with "alter sequence"
    --EXECUTE 'SELECT setval( "' || seqname || '", ' || cast(c as character varying) || ', false)'; DOES NOT WORK!!!
    EXECUTE 'alter sequence ' || seqname ||' restart with ' || cast(c as character varying);
    RETURN nextval(seqname)-1;
  END;
$body$ LANGUAGE 'plpgsql';

select sequence_name, PG_CLASS.relname, PG_ATTRIBUTE.attname,
       reset_sequence(PG_CLASS.relname,PG_ATTRIBUTE.attname)
from PG_CLASS
join PG_ATTRIBUTE on PG_ATTRIBUTE.attrelid = PG_CLASS.oid
join information_schema.sequences
     on information_schema.sequences.sequence_name = PG_CLASS.relname || '_' || PG_ATTRIBUTE.attname || '_seq'
where sequence_schema='public';

перепроверить всю последовательность в публичной функции схемы

CREATE OR REPLACE FUNCTION public.recheck_sequence (
)
RETURNS void AS
$body$
DECLARE
  _table_name VARCHAR;
  _column_name VARCHAR;  
  _sequence_name VARCHAR;
BEGIN
  FOR _table_name IN SELECT tablename FROM pg_catalog.pg_tables WHERE schemaname = 'public' LOOP
    FOR _column_name IN SELECT column_name FROM information_schema.columns WHERE table_name = _table_name LOOP
        SELECT pg_get_serial_sequence(_table_name, _column_name) INTO _sequence_name;
        IF _sequence_name IS NOT NULL THEN 
            EXECUTE 'SELECT setval('''||_sequence_name||''', COALESCE((SELECT MAX('||quote_ident(_column_name)||')+1 FROM '||quote_ident(_table_name)||'), 1), FALSE);';
        END IF;
    END LOOP;   
  END LOOP;
END;
$body$
LANGUAGE 'plpgsql'
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER
COST 100;

еще один plpgsql-сбрасывается только если max(att) > then lastval

do --check seq not in sync
$$
declare
 _r record;
 _i bigint;
 _m bigint;
begin
  for _r in (
    SELECT relname,nspname,d.refobjid::regclass, a.attname, refobjid
    FROM   pg_depend    d
    JOIN   pg_attribute a ON a.attrelid = d.refobjid AND a.attnum = d.refobjsubid
    JOIN pg_class r on r.oid = objid
    JOIN pg_namespace n on n.oid = relnamespace
    WHERE  d.refobjsubid > 0 and  relkind = 'S'
   ) loop
    execute format('select last_value from %I.%I',_r.nspname,_r.relname) into _i;
    execute format('select max(%I) from %s',_r.attname,_r.refobjid) into _m;
    if coalesce(_m,0) > _i then
      raise info '%',concat('changed: ',_r.nspname,'.',_r.relname,' from:',_i,' to:',_m);
      execute format('alter sequence %I.%I restart with %s',_r.nspname,_r.relname,_m+1);
    end if;
  end loop;

end;
$$
;

также комментируя строку --execute format('alter sequence даст список, фактически не сбрасывая значение


перезагрузить все последовательности 1 использовать:

-- Create Function
CREATE OR REPLACE FUNCTION "sy_restart_seq_to_1" (
    relname TEXT
)
RETURNS "pg_catalog"."void" AS
$BODY$

DECLARE

BEGIN
    EXECUTE 'ALTER SEQUENCE '||relname||' RESTART WITH 1;';
END;
$BODY$

LANGUAGE 'plpgsql';

-- Use Function
SELECT 
    relname
    ,sy_restart_seq_to_1(relname)
FROM pg_class
WHERE relkind = 'S';

эта проблема возникает со мной при использовании entity framework для создания базы данных, а затем заполнения базы данных исходными данными, это делает несоответствие последовательности.

Я решил это, создав скрипт для запуска после заполнения базы данных:

DO
$do$
DECLARE tablename text;
BEGIN
    -- change the where statments to include or exclude whatever tables you need
    FOR tablename IN SELECT table_name FROM information_schema.tables WHERE table_schema='public' AND table_type='BASE TABLE' AND table_name != '__EFMigrationsHistory'
        LOOP
            EXECUTE format('SELECT setval(pg_get_serial_sequence(''"%s"'', ''Id''), (SELECT MAX("Id") + 1 from "%s"))', tablename, tablename);
    END LOOP;
END
$do$

Если вы видите эту ошибку при загрузке пользовательских данных SQL для инициализации, еще один способ избежать этого:

вместо того, чтобы писать:

INSERT INTO book (id, name, price) VALUES (1 , 'Alchemist' , 10),

удалить id (первичный ключ) из исходных данных

INSERT INTO book (name, price) VALUES ('Alchemist' , 10),

это сохраняет последовательность Postgres в синхронизации !


этот ответ является копией с Мауро.

drop function IF EXISTS rebuilt_sequences() RESTRICT;
CREATE OR REPLACE FUNCTION  rebuilt_sequences() RETURNS integer as
$body$
  DECLARE sequencedefs RECORD; c integer ;
  BEGIN
    FOR sequencedefs IN Select
      DISTINCT(constraint_column_usage.table_name) as tablename,
      constraint_column_usage.column_name as columnname,
      replace(replace(columns.column_default,'''::regclass)',''),'nextval(''','') as sequencename
      from information_schema.constraint_column_usage, information_schema.columns
      where constraint_column_usage.table_schema ='public' AND 
      columns.table_schema = 'public' AND columns.table_name=constraint_column_usage.table_name
      AND constraint_column_usage.column_name = columns.column_name
      AND columns.column_default is not null 
      ORDER BY sequencename
   LOOP    
      EXECUTE 'select max('||sequencedefs.columnname||') from ' || sequencedefs.tablename INTO c;
      IF c is null THEN c = 0; END IF;
      IF c is not null THEN c = c+ 1; END IF;
      EXECUTE 'alter sequence ' || sequencedefs.sequencename ||' minvalue '||c ||' start ' || c ||' restart  with ' || c;
   END LOOP;

   RETURN 1; END;
$body$ LANGUAGE plpgsql;

select rebuilt_sequences();

Я потратил час, пытаясь получить ответ djsnowsill для работы с базой данных, используя смешанные таблицы и столбцы Case, а затем, наконец, наткнулся на решение благодаря комментарию Мануэля Дарво, но я думал, что могу сделать его немного яснее для всех:

CREATE OR REPLACE FUNCTION "reset_sequence" (tablename text, columnname text)
RETURNS "pg_catalog"."void" AS
$body$
DECLARE
BEGIN
EXECUTE format('SELECT setval(pg_get_serial_sequence(''%1$I'', %2$L),
        (SELECT COALESCE(MAX(%2$I)+1,1) FROM %1$I), false)',tablename,columnname);
END;
$body$  LANGUAGE 'plpgsql';

SELECT format('%s_%s_seq',table_name,column_name), reset_sequence(table_name,column_name) 
FROM information_schema.columns WHERE column_default like 'nextval%';

это имеет преимущество:

  • не предполагая, что столбец ID пишется определенным образом.
  • не предполагая, что все таблицы имеют последовательность.
  • работа для смешанного случая имена таблиц / столбцов.
  • использование формата, чтобы быть более кратким.

чтобы объяснить, проблема была в том, что pg_get_serial_sequence строки, чтобы выяснить, что вы имеете в виду, так что если вы:

"TableName" --it thinks it's a table or column
'TableName' --it thinks it's a string, but makes it lower case
'"TableName"' --it works!

это достигается с помощью ''%1$I'' в строке формата, '' делает Апостроф 1$ означает первый arg, и I значит в кавычки


ответ Клауса самый полезный, execpt для маленького Мисс : вы необходимо добавить DISTINCT в инструкцию select.

однако, если вы уверены, что имена таблиц + столбцов не могут быть эквивалентны для двух разных таблиц, вы можете использовать :

select sequence_name, --PG_CLASS.relname, PG_ATTRIBUTE.attname
       reset_sequence(split_part(sequence_name, '_id_seq',1))
from PG_CLASS
join PG_ATTRIBUTE on PG_ATTRIBUTE.attrelid = PG_CLASS.oid
join information_schema.sequences
     on information_schema.sequences.sequence_name = PG_CLASS.relname || '_' || PG_ATTRIBUTE.attname
where sequence_schema='public';

, который является расширением решения user457226 для случая, когда некоторое заинтересованное имя столбца не является "ID".


уродливый хак, чтобы исправить это, используя некоторую магию оболочки, не отличное решение, но может вдохновить других с подобными проблемами:)

pg_dump -s <DATABASE> | grep 'CREATE TABLE' | awk '{print "SELECT setval(#"  "_id_seq#, (SELECT MAX(id) FROM "  "));"}' | sed "s/#/'/g" | psql <DATABASE> -f -

попробовать переиндексация.

UPDATE: как указано в комментариях, это был ответ на исходный вопрос.


SELECT setval... делает JDBC Борк, так что вот Java-совместимый способ сделать это:

-- work around JDBC 'A result was returned when none was expected.'
-- fix broken nextval due to poorly written 20140320100000_CreateAdminUserRoleTables.sql
DO 'BEGIN PERFORM setval(pg_get_serial_sequence(''admin_user_role_groups'', ''id''), 1 + COALESCE(MAX(id), 0), FALSE) FROM admin_user_role_groups; END;';