Postgres ręcznie zmienia sekwencję

189

Próbuję ustawić sekwencję na określoną wartość.

SELECT setval('payments_id_seq'), 21, true

Daje to błąd:

ERROR: function setval(unknown) does not exist

Używanie ALTER SEQUENCEteż nie działa?

ALTER SEQUENCE payments_id_seq LASTVALUE 22

Jak można to zrobić?

Ref: https://www.postgresql.org/docs/current/static/functions-sequence.html

stef
źródło
4
Wydaje się, że setval()ma co najmniej dwa argumenty.

Odpowiedzi:

262

Nawiasy są źle umieszczone:

SELECT setval('payments_id_seq', 21, true);  # next value will be 22

W przeciwnym razie sprawdzasz setvalz jednym argumentem, podczas gdy wymaga on dwóch lub trzech.

NPE
źródło
2
Co oznacza ostatni argument „prawda”?
inafalcao
15
trueoznacza, że ​​następną wartością będzie podana liczba + 1, w tym przypadku 22. falseoznacza, że ​​następną wartością będzie podana liczba, lub 21. Domyślnie setval będzie zachowywał się tak, jakby truezostał wybrany. Więcej informacji: postgresql.org/docs/9.6/static/functions-sequence.html
Tom Mertz
1
zaletą tej select setvalskładni alter sequencejest to, że można w niej używać zagnieżdżonych zapytań, na przykład do select max(id) from payments.
mariotomo
186

Ta składnia nie jest poprawna w żadnej wersji PostgreSQL:

ALTER SEQUENCE payments_id_seq LASTVALUE 22

To by działało:

ALTER SEQUENCE payments_id_seq RESTART WITH 22;

i jest równoważny:

SELECT setval('payments_id_seq', 22, FALSE);

Więcej w aktualnym podręczniku funkcjiALTER SEQUENCE i sekwencji .

Należy pamiętać, że setval()spodziewa się, albo (regclass, bigint)czy (regclass, bigint, boolean). W powyższym przykładzie dostarczam literały bez typów . To też działa. Ale jeśli podajesz zmienne typowane do funkcji, możesz potrzebować rzutowania typu jawnego, aby spełnić rozdzielczość typu funkcji. Lubić:

SELECT setval(my_text_variable::regclass, my_other_variable::bigint, FALSE);

W przypadku powtarzających się operacji możesz być zainteresowany:

ALTER SEQUENCE payments_id_seq START WITH 22; -- set default
ALTER SEQUENCE payments_id_seq RESTART;       -- without value

START [WITH]przechowuje domyślny RESTARTnumer, który służy do kolejnych RESTARTpołączeń bez wartości. Do ostatniej części potrzebujesz Postgres 8.4 lub nowszy.

Erwin Brandstetter
źródło
4
ALTER SEQUENCE [sequence] RESTART WITH (SELECT MAX(col) from table);nie działa, a SELECT setval('sequence', (SELECT (MAX(col) from table), TRUE);działa. Otrzymuję błąd składniowy. (Postgres 9.4)
NuclearPeon
1
W poleceniu DDL nie jest dozwolone podzapytanie („polecenie narzędzia”). Zobacz: stackoverflow.com/a/36025963/939860
Erwin Brandstetter
1
@MitalPritmani: Być może potrzebujesz rzutowania tekstu. Rozważ dodane instrukcje powyżej.
Erwin Brandstetter,
1
@NuclearPeon Myślę, że masz na myśli, SELECT setval('sequence', (SELECT MAX(col) from table), TRUE);że inaczej twoje pareny się nie ustawią .
dland
1
@dland: Poza: krótszy i szybszy odpowiednik: SELECT setval('seq', max(col)) FROM tbl;Patrz: stackoverflow.com/a/23390399/939860
Erwin Brandstetter
33

Posługiwać się select setval('payments_id_seq', 21, true);

setval zawiera 3 parametry:

  • Pierwszy parametr to sequence_name
  • Drugi parametr to Dalej nextval
  • Trzeci parametr jest opcjonalny.

Użycie true lub false w 3. parametrze setval jest następujące:

SELECT setval('payments_id_seq', 21);           // Next nextval will return 22
SELECT setval('payments_id_seq', 21, true);     // Same as above 
SELECT setval('payments_id_seq', 21, false);    // Next nextval will return 21

Aby lepiej zakodować na stałe nazwę sekwencji, kolejną wartość sekwencji i poprawnie obsługiwać pustą tabelę kolumn, możesz użyć następującego sposobu:

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

gdzie table_namejest nazwa tabeli, idto nazwa primary keytabeli

VaibsVB
źródło
Dziękuję Ci! Ostatnie wyrażenie jest dokładnie tym, czego szukałem. Pozwala mi zarezerwować wartości sekwencji w celu późniejszego wstawienia partii.
Timur
8
setval('sequence_name', sequence_value)
Andrzej Bobak
źródło
0

Nie próbuję zmienić sekwencji za pomocą setval. Ale za pomocą ALTERI wydano, jak poprawnie napisać nazwę sekwencji. I to działa tylko dla mnie:

  1. Sprawdź wymaganą nazwę sekwencji za pomocą SELECT * FROM information_schema.sequences;

  2. ALTER SEQUENCE public."table_name_Id_seq" restart {number};

    W moim przypadku tak było ALTER SEQUENCE public."Services_Id_seq" restart 8;

alanextar
źródło