Kluczową rzeczą do zrozumienia jest to, że tabele SQL nie mają kolejności . Kolejność wierszy widoczna po SELECT
bez ORDER BY
pozostaje tylko taka sama, ponieważ baza danych szybciej pobiera je w tej kolejności niż w innej. PostgreSQL zwróci wiersze w tej kolejności tylko wtedy, gdy wykonasz sekwencyjne skanowanie tabeli; jeśli może użyć indeksu dla zapytania, zazwyczaj otrzymasz wiersze w innej kolejności.
Ta odpowiedź, którą napisałem wcześniej, może okazać się pouczająca.
W PostgreSQL UPDATE
s do wierszy mogą przenieść je w inne miejsce w tabeli, zmieniając kolejność, w jakiej są zwracane. Podobnie proces automatycznego odkurzania w tle i różne inne operacje, takie jak VACUUM
i CLUSTER
.
Więc musisz nigdy polegać na "domyślnym" porządkowaniu wszystkiego. Jeśli chcesz nadać wierszom jakiś porządek, muszą mieć klucz, według którego możesz je posortować.
Jeśli utworzyłeś tabelę bez klucza i teraz zdajesz sobie sprawę, że powinna go mieć, możesz być w stanie wyjść z sytuacji za pomocą ctid
kolumna systemowa. Nie polegać na tym do użytku produkcyjnego, jest to wewnętrzna kolumna systemu, która jest widoczna dla użytkowników tylko w celu odzyskiwania awaryjnego i celów diagnostycznych. Najpierw sprawdź, czy fizyczne zamawianie na dysku jest rzeczywiście taką kolejnością, jaką chcesz:
SELECT row_number() OVER () AS mytable_id, *
FROM mytable
ORDER BY ctid;
Jeśli tak, możesz dodać nową kolumnę klucza, która jest wstępnie ustawiona dla klucza z automatyczną inkrementacją zastosowanego w kolejności wierszy na dysku. Można to zrobić na dwa sposoby. Najbezpieczniejszy jest:
BEGIN;
LOCK TABLE mytable IN ACCESS EXCLUSIVE MODE;
ALTER TABLE mytable RENAME TO mytable_old;
CREATE TABLE mytable (id SERIAL PRIMARY KEY, LIKE mytable_old INCLUDING ALL);
INSERT INTO mytable
SELECT row_number() OVER () AS id, *
FROM mytable_old
ORDER BY ctid;
SELECT setval('mytable_id_seq', (SELECT max(id)+1 FROM mytable));
COMMIT;
następnie, gdy upewnisz się, że wyniki są zadowalające, DROP TABLE mytable_old;
. Zobacz to demo:http://sqlfiddle.com/#!12/2cb99/2
Szybkim i łatwym, ale mniej bezpiecznym sposobem jest po prostu utworzenie kolumny i poleganie na przepisaniu tabeli przez PostgreSQL od początku do końca:
ALTER TABLE mytable ADD COLUMN mytable_id SERIAL PRIMARY KEY;
Nie ma absolutnej gwarancji PostgreSQL przypisze identyfikatory w odpowiedniej kolejności, chociaż w praktyce to zrobi. Zobacz to demo SQLFiddle.
Pamiętaj, że gdy używasz SEQUENCE
(czyli właśnie SERIAL
kolumna tworzy) jest kilka zachowań, których możesz się nie spodziewać. Gdy wstawiasz wiele wierszy naraz, wiersze mogą niekoniecznie otrzymać przypisane identyfikatory w dokładnej kolejności, w jakiej są, i mogą „wyświetlać się” (stać się widoczne) w innej kolejności niż kolejność, w której zostały przypisane identyfikatory i wstawione w. Ponadto, jeśli transakcje zostaną wycofane, wygenerowany identyfikator jest wyrzucany na zawsze, więc pojawiają się luki w numeracji. Jest to bardzo dobre, jeśli chcesz, aby Twoja baza danych była szybka, ale nie jest to idealne rozwiązanie, jeśli chcesz numerować bez przerw. Jeśli tego potrzebujesz, wyszukaj „sekwencja bez przerw postgresql”.