Auto Increment Para PostGreSQL
Publicado por João em 21 ' setembro 2008
Auto incremento é uma facilidade muito usada em gerenciadores de bancos de dados, como MySQL. Serve para a cada inserção em uma tabela seja gerado um índice único, numérico crescente, facilitando a indexação das tabelas.
Ex no MySQL 5:
CREATE TABLE teste (
idTeste INT NOT NULL AUTO INCREMENT,
nome VARCHAR(20) NOT NULL
);
Crio alguns INSERTS:
INSERT INTO teste(nome) values(‘PRIMEIRA LINHA’);
INSERT INTO teste(nome) values(‘SEGUNDA LINHA’);
SELECT * FROM teste;
| idTeste | nome |
| 1 | PRIMEIRA LINHA |
| 2 | SEGUNDA LINHA |
Já no PostGreSQL, essa facilidade é obtida de uma forma um pouco diferente:
Primeiro temos que criar uma sequencia:
CREATE SEQUENCE sq_teste_autoIncrement START WITH 1 NO MINVALUE NO MAXVALUE;
Entao crie a tabela:
CREATE TABLE teste (
idTeste INTEGER NOT NULL DEFAULT nextval(‘sq_teste_autoIncrement’),
nome CHARACTER VARYING(20) NOT NULL
);
Com os INSERTS, o resultado é o mesmo:
INSERT INTO teste(nome) values(‘PRIMEIRA LINHA’);
INSERT INTO teste(nome) values(‘SEGUNDA LINHA’);
SELECT * FROM teste;
| idTeste | nome |
| 1 | PRIMEIRA LINHA |
| 2 | SEGUNDA LINHA |
Para facilitar esse trabalho, um tipo do PostGreSQL para esse tipo de operação é o tipo SERIAL:
CREATE TABLE teste (
idTeste SERIAL NOT NULL,
nome CHARACTER VARYING(20) NOT NULL
);
Quando se executa essa QUERY, o PostGreSQL faz:
1 – Cria uma sequencia de nome <NomeTabela>_<NomeColuna>_seq
2 – Define que a coluna é do tipo INTEGER e que o valor DEFAULT é nextval(<NomeTabela>_<NomeColuna>_seq)
Eu prefiro criar eu mesmo as sequencias e definir o valor padrão dos campos com a função nextval(), as duas operações não contam diferenças para o SGBD (Até porque no fim fazem a mesma coisa), mas criar passo a passo torna o código mais legível – pelo menos pra mim!
Mas, cuidado!
Tente fazer o seguinte (Isso eles não contam na documentação!)
CREATE TABLE teste (
idTeste INTEGER NOT NULL DEFAULT nextval(‘sq_teste_autoIncrement’),
nome CHARACTER VARYING(20) NOT NULL
);
INSERT INTO teste(nome) values(‘PRIMEIRA LINHA’);
INSERT INTO teste(nome) values(‘SEGUNDA LINHA’);
SELECT * FROM teste;
| idTeste | nome |
| 1 | PRIMEIRA LINHA |
| 2 | SEGUNDA LINHA |
Agora:
SELECT currval(‘sq_teste_autoIncrement’) AS valorAutoIncrement;
| valorAutoIncrement |
| 3 |
Obviamente, ao executar outro INSERT o campo idTeste será preenchido com 3, concorda?
Mas, se executar um INSERT assim:
INSERT INTO teste(idTeste, nome) values(5, ‘QUINTA LINHA’);
| idTeste | nome |
| 1 | PRIMEIRA LINHA |
| 2 | SEGUNDA LINHA |
| 5 | QUINTA LINHA |
SELECT currval(‘sq_teste_autoIncrement’) AS valorAutoIncrement;
| valorAutoIncrement |
| 3 |
O que acontece é que a sequencia só incrementa caso seja necessário um valor DEFAULT para o campo, ou seja, apenas quando o campo não for definido em um INSERT.
Como o valor da SEQUENCE é “3″, no próximo segundo INSERT no PostGreSQL poderá acontecer o seguinte:
INSERT INTO teste(nome) values(‘QUARTA LINHA’);
INSERT INTO teste(nome) values(‘QUINTA LINHA DUPLICADA’);
| idTeste | nome |
| 1 | PRIMEIRA LINHA |
| 2 | SEGUNDA LINHA |
| 3 | TERCEIRA LINHA |
| 5 | QUINTA LINHA |
| 4 | QUARTA LINHA |
| 5 | QUINTA LINHA DUPLICADA |
No MySQL, o valor do AUTO INCREMENT nunca possui um valor menor do que MAX(nomeCampo) + 1 do campo em que está sendo usado, evitando esse problema.
Imagine o erro de “duplicar valor da chave viola a restrição de unicidade” caso idTeste fosse chave primária! Entao cuidado…
Um abraço.
Espero ter ajudado!
Marcelo disse
Lo mejor es usar el tipo de datos SERIAL :
CREATE TABLE teste (
idTeste SERIAL NOT NULL,
nome CHARACTER VARYING(20) NOT NULL
);
SERIAL Crea una secuencia de forma automática y utiliza el tipo de datos INT como base, autoincrementandose automáticamente en 1.
SR.STORK disse
Ai valeu pela instrução, mais tem uma outra duvida tenho uma tabela com mais ou menos 22 mil linHa pra inserir no banco de dados postesql, mais ela esta no excel a alguma maneira de tranferir este arquivos e deposi anexalos a minha tabela da banco
sem ter que usar em todos
insert into NOME_dA_TABELA VALUES (……….);
PARA TODOS?