Най-важното нещо, което трябва да разберете, е, че SQL таблиците нямат подреждане . Редът на редовете, който виждате, когато SELECT
без ORDER BY
само остава същото, защото е по-бързо базата данни да ги получи в този ред, отколкото в друг ред. PostgreSQL ще върне редове в този ред само когато правите последователно сканиране на таблицата; ако може да използва индекс за заявката, тогава обикновено ще получите редовете в друг ред.
Може да намерите този отговор, който написах по-рано, информативен.
В PostgreSQL, UPDATE
s to rows може да ги премести на друго място в таблицата, променяйки реда, в който се връщат. Така може и фоновият процес на автоматично вакуумиране и различни други операции като VACUUM
и CLUSTER
.
Така че не трябва никога разчитайте на подреждането по подразбиране за всичко. Ако искате да дадете на редовете някакъв ред, те трябва имат ключ, по който можете да ги сортирате.
Ако сте създали таблица без ключ и сега осъзнавате, че трябва да има такъв, може да успеете да се възстановите от ситуацията, като използвате ctid
системна колона. Нене разчитайте на това за производствена употреба, това е вътрешна колона на системата, която е видима за потребителите само за спешно възстановяване и диагностични цели. Първо, вижте дали физическото подреждане на диска всъщност е реда, който искате:
SELECT row_number() OVER () AS mytable_id, *
FROM mytable
ORDER BY ctid;
Ако е така, можете да добавите нова колона с ключ, която е предварително зададена за автоматично увеличен ключ, приложен в реда на редовете на диска. Има два начина да направите това. Най-безопасното е:
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;
след това след като сте сигурни, че сте доволни от резултатите, DROP TABLE mytable_old;
. Вижте тази демонстрация:http://sqlfiddle.com/#!12/2cb99/2
Бърз и лесен, но по-малко безопасен начин е просто да създадете колоната и да разчитате на PostgreSQL да пренапише таблицата от началото до края:
ALTER TABLE mytable ADD COLUMN mytable_id SERIAL PRIMARY KEY;
Няма абсолютно никаква гаранция че PostgreSQL ще присвои идентификаторите по ред, въпреки че на практика ще го направи. Вижте тази демонстрация на SQLFiddle.
Имайте предвид, че когато използвате SEQUENCE
(което е SERIAL
колона създава) има няколко поведения, които може да не очаквате. Когато вмъквате няколко реда наведнъж, редовете може да не получават непременно присвоени идентификационни номера в точния ред, в който очаквате, и може да се „появят“ (да станат видими) в различен ред от реда, в който са били присвоени идентификатори и са били вмъкнати in. Освен това, ако транзакциите се върнат назад, генерираният идентификатор се изхвърля завинаги, така че получавате пропуски в номерирането. Това е много добре, ако искате вашата база данни да бъде бърза, но не е идеално, ако искате номериране без празнини. Ако това е, от което се нуждаете, потърсете „последователност без празнини на postgresql“.