A coisa crucial a entender é que as tabelas SQL não têm uma ordenação . A ordem das linhas que você vê quando
SELECT
sem um ORDER BY
só permanece o mesmo porque é mais rápido para o banco de dados obtê-los nessa ordem do que em outra ordem. O PostgreSQL só retornará linhas nesta ordem quando você fizer uma varredura sequencial na tabela; se ele puder usar um índice para a consulta, você geralmente obterá as linhas em outra ordem. Você pode achar esta resposta que escrevi anteriormente informativa.
No PostgreSQL,
UPDATE
s para linhas podem movê-los para um local diferente na tabela, alterando a ordem em que são retornados. Assim como o processo de autovacuum em segundo plano e várias outras operações como VACUUM
e CLUSTER
. Então você deve nunca confie na ordenação "padrão" para qualquer coisa. Se você quiser dar às linhas algum tipo de ordem, elas devem tem uma chave na qual você pode classificá-los.
Se você criou uma tabela sem uma chave e agora percebe que ela deveria ter uma, você pode se recuperar da situação usando o
ctid
coluna do sistema. não contar com isso para uso em produção, é uma coluna interna do sistema visível para os usuários apenas para fins de diagnóstico e recuperação de emergência. Primeiro, veja se o pedido físico no disco é realmente o pedido que você deseja:SELECT row_number() OVER () AS mytable_id, *
FROM mytable
ORDER BY ctid;
Se for, você pode adicionar uma nova coluna de chave predefinida para uma chave incrementada automaticamente aplicada na ordem das linhas no disco. Existem duas maneiras de fazer isso. O mais seguro é:
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;
então, quando tiver certeza de que está satisfeito com os resultados,
DROP TABLE mytable_old;
. Veja esta demonstração:http://sqlfiddle.com/#!12/2cb99/2 Uma maneira rápida e fácil, mas menos segura, é apenas criar a coluna e confiar no PostgreSQL reescrevendo a tabela do começo ao fim:
ALTER TABLE mytable ADD COLUMN mytable_id SERIAL PRIMARY KEY;
Não há absolutamente nenhuma garantia que o PostgreSQL atribuirá os IDs em ordem, embora na prática o faça. Veja esta demonstração do SQLFiddle.
Esteja ciente de que quando você usa uma
SEQUENCE
(que é o que um SERIAL
coluna cria) existem alguns comportamentos que você pode não esperar. Quando você insere várias linhas de uma vez, as linhas podem não necessariamente receber os IDs atribuídos na ordem exata que você espera, e elas podem "aparecer" (tornar-se visíveis) em uma ordem diferente da ordem em que foram atribuídos os IDs e inseridos Além disso, se as transações forem revertidas, o ID gerado será descartado para sempre, então você terá lacunas na numeração. Isso é muito bom se você deseja que seu banco de dados seja rápido, mas não é ideal se você deseja uma numeração sem lacunas. Se é isso que você precisa, procure por "postgresql gapless sequence".