Dúvidas básicas de PostgreSQL (diversas)

10/02/2013

3

Bom dia, colegas!

Considerem a seguinte situação: eu criei um BD chamado "escola" e uma tabela chamada "alunos". Na tabela "alunos", criei as seguintes colunas, nesta ordem: aluno (varchar), id_aluno (int) e data_nasc (date). Setei "aluno" como sendo NOT NULL e "id_aluno" como sendo NOT NULL e "auto increment" (serial).
Na hora de dar um "INSERT INTO alunos VALUE (etc, etc, etc);", obviamente não será preciso que seja inserido o campo "id_aluno", pois o próprio SGBD cuida disso pra mim. Acontece que eu não sabia como deveria proceder. Pra mim, o fato de digitar: "INSERT INTO alunos VALUE ('José dos Anzóis Furados', 26/09/2003)" já fazia com que o SGBD entendesse o que deveria ser feito. Porém, na hora de dar um "select * from" na tabela vi que o campo "data_nasc" estava vazio e o "id_aluno" estava "-2008"! Tudo bem, então, vamos consertar o prejuízo manualmente: dei um UPDATE e setei o campo "id_aluno" como deveria estar! Porém, ao tentar inserir outro aluno (somente com o nome do aluno e mais nada) o SGDB reclamou:

escola=# INSERT INTO alunos VALUES ('José Bibiano Trigueiro');
ERROR: duplicate key value violates unique constraint "alunos_pkey"
DETAIL: Key (id_aluno)=(1) already exists.

Diante disto eu pergunto:

1. Como "pular" o id_aluno na hora de inserir dados na tabela?
2. Como consertar esse erro para que ele volte a inserir os dados corretos na tabela, já que ele vai tentar inserir a chave inteira 1 sem sucesso sempre? Ou seja, se uma coluna é auto increment e mesmo assim for setado um valor para ela "na marra", na próxima iteração o SGDB vai querer usar o valor que foi setado na marra e ele vai reclamar. O que fazer?
3. Há ainda uma pergunta que não tem nada a ver com a situação acima: como inserir uma coluna "status" como sendo do tipo bit? Tentei fazê-lo com o comando "UPDATE alunos ADD COLUMN status bit;" e ele me retornou a seguinte mensagem:

ERROR: syntax error at or near "COLUMN"
LINE 1: UPDATE alunos ADD COLUMN status bit;

No caso da pergunta 1, alguém poderia dizer: "Ah! isso é fácil! É só digitar 'INSERT INTO alunos (aluno, data_nasc) VALUE (etc, etc, etc);'" Mas se a tabela tiver 50 colunas? Vou ter que digitar TODAS as colunas menos a que eu não quero, todas as vezes que eu for inserir algum dado na tabela? Ex: "INSERT INTO alunos (aluno, data_nasc, pai, mae, serie, turno, turma, professora, status, etc, etc, etc, etc, etc, etc, etc, etc...) VALUE (etc, etc, etc...);"

De já, agradeço a ajuda!
Grande abraço a todos!
Responder

Posts

14/02/2013

Jair N.

Boa Tarde, conforme seu enunciado, cheguei a alguns erros encontrados:

1º Você não consegue alterar um campo do tipo INT para SERIAL, não sei como você fez isso, é impossível alterá-lo, mas, para funcionar, teria que criar um SEQUENCIAL a exemplo: CREATE SEQUENCE seq_alunos INCREMENT 1 MINVALUE 1 NO MAXVALUE START 1 CACHE 1, e para o valor INT inteiro informe o valor DEFAULT o incremento a exemplo: DEFAULT NEXTVAL('seq_alunos'), ou excluir o campo atual id_aluno e recriá-lo novamente com esse tipo específico SERIAL que cria automaticamente todo esse procedimento;

2º A clausula "INSERT INTO...tem que identificar os campos que recebem os parâmetros, caso contrario terá que definir após o comando "VALUES" e não "VALUE" a mesma ordem dos atributos cadastrados com exceção do campo SERIAL, não incluindo aqui o que é do tipo INT inteiro do id_alunos como valor DEFAULT o SEQUENCIAL, neste caso informe o parâmetro como NULL (nulo);

3º O campo data não pode ser "26/09/2003" sem aspas, para o sistema você está fazendo um calculo e dividindo tudo isso e o termo desta na divisão entre 26/09/2003 é um valor inteiro de 0 zero, para um campo data vazio nulo. A conversão correta utilize no formato americano do banco de dados "'YYYY-MM-DD'" entre aspas ou convertendo com um comando CAST a data entre aspas;

4º Não importa quantas vezes for incluir registros, o comando INSERT deve ser repetido com os seus atributos e parâmetros de quem está recebendo o que. Consulte no manual do PostgreSQL ou qualquer outro manual de banco de dados referente a clausula INSERT são especificas e com pouca ou quase nenhuma diferença.

Outra banco de dados existem regras e mais regras, facilitadores e funções internas que otimizam processos e procedimentos não tem como fugir disso não, pode facilitar mas fugir as regras é impossível.

PS: A duplicação do campo chave id_aluno, só existe se, o seqüêncial não foi executado como DEFAULT, isso pelo uso de um valor incluído no INSERT ou UPDATE, e continua com o valor anterior no START. veja isso com o comando SELECT CURVAL('seq_alunos') entre aspas o seqüêncial após o NEXTVAL inicial...


Bom dia, colegas!

Considerem a seguinte situação: eu criei um BD chamado "escola" e uma tabela chamada "alunos". Na tabela "alunos", criei as seguintes colunas, nesta ordem: aluno (varchar), id_aluno (int) e data_nasc (date). Setei "aluno" como sendo NOT NULL e "id_aluno" como sendo NOT NULL e "auto increment" (serial).
Na hora de dar um "INSERT INTO alunos VALUE (etc, etc, etc);", obviamente não será preciso que seja inserido o campo "id_aluno", pois o próprio SGBD cuida disso pra mim. Acontece que eu não sabia como deveria proceder. Pra mim, o fato de digitar: "INSERT INTO alunos VALUE ('José dos Anzóis Furados', 26/09/2003)" já fazia com que o SGBD entendesse o que deveria ser feito. Porém, na hora de dar um "select * from" na tabela vi que o campo "data_nasc" estava vazio e o "id_aluno" estava "-2008"! Tudo bem, então, vamos consertar o prejuízo manualmente: dei um UPDATE e setei o campo "id_aluno" como deveria estar! Porém, ao tentar inserir outro aluno (somente com o nome do aluno e mais nada) o SGDB reclamou:

escola=# INSERT INTO alunos VALUES ('José Bibiano Trigueiro');
ERROR: duplicate key value violates unique constraint "alunos_pkey"
DETAIL: Key (id_aluno)=(1) already exists.

Diante disto eu pergunto:

1. Como "pular" o id_aluno na hora de inserir dados na tabela?
2. Como consertar esse erro para que ele volte a inserir os dados corretos na tabela, já que ele vai tentar inserir a chave inteira 1 sem sucesso sempre? Ou seja, se uma coluna é auto increment e mesmo assim for setado um valor para ela "na marra", na próxima iteração o SGDB vai querer usar o valor que foi setado na marra e ele vai reclamar. O que fazer?
3. Há ainda uma pergunta que não tem nada a ver com a situação acima: como inserir uma coluna "status" como sendo do tipo bit? Tentei fazê-lo com o comando "UPDATE alunos ADD COLUMN status bit;" e ele me retornou a seguinte mensagem:

ERROR: syntax error at or near "COLUMN"
LINE 1: UPDATE alunos ADD COLUMN status bit;

No caso da pergunta 1, alguém poderia dizer: "Ah! isso é fácil! É só digitar 'INSERT INTO alunos (aluno, data_nasc) VALUE (etc, etc, etc);'" Mas se a tabela tiver 50 colunas? Vou ter que digitar TODAS as colunas menos a que eu não quero, todas as vezes que eu for inserir algum dado na tabela? Ex: "INSERT INTO alunos (aluno, data_nasc, pai, mae, serie, turno, turma, professora, status, etc, etc, etc, etc, etc, etc, etc, etc...) VALUE (etc, etc, etc...);"

De já, agradeço a ajuda!
Grande abraço a todos!
Responder
Boa Tarde, conforme seu enunciado, cheguei a alguns erros encontrados:

1º Você não consegue alterar um campo do tipo INT para SERIAL, não sei como você fez isso, é impossível alterá-lo, mas, para funcionar, teria que criar um SEQUENCIAL a exemplo: CREATE SEQUENCE seq_alunos INCREMENT 1 MINVALUE 1 NO MAXVALUE START 1 CACHE 1, e para o valor INT inteiro informe o valor DEFAULT o incremento a exemplo: DEFAULT NEXTVAL('seq_alunos'), ou excluir o campo atual id_aluno e recriá-lo novamente com esse tipo específico SERIAL que cria automaticamente todo esse procedimento;


Desculpe o mal entendido. Realmente eu DELETEI o campo e fiz de novo como serial. Mas o teu comentário não foi em vão, uma vez que eu aprendi que é IMPOSSÍVEL transformar um int num serial e sobre criar um sequencial.

2º A clausula "INSERT INTO...tem que identificar os campos que recebem os parâmetros, caso contrario terá que definir após o comando "VALUES" e não "VALUE" a mesma ordem dos atributos cadastrados com exceção do campo SERIAL, não incluindo aqui o que é do tipo INT inteiro do id_alunos como valor DEFAULT o SEQUENCIAL, neste caso informe o parâmetro como NULL (nulo);


Verdade!!!

3º O campo data não pode ser "26/09/2003" sem aspas, para o sistema você está fazendo um calculo e dividindo tudo isso e o termo desta na divisão entre 26/09/2003 é um valor inteiro de 0 zero, para um campo data vazio nulo. A conversão correta utilize no formato americano do banco de dados "'YYYY-MM-DD'" entre aspas ou convertendo com um comando CAST a data entre aspas;


Eu usei '21-04-1976' e deu certo, no formato BR mesmo!

4º Não importa quantas vezes for incluir registros, o comando INSERT deve ser repetido com os seus atributos e parâmetros de quem está recebendo o que. Consulte no manual do PostgreSQL ou qualquer outro manual de banco de dados referente a clausula INSERT são especificas e com pouca ou quase nenhuma diferença.

Outra banco de dados existem regras e mais regras, facilitadores e funções internas que otimizam processos e procedimentos não tem como fugir disso não, pode facilitar mas fugir as regras é impossível.


Notei. :)

PS: A duplicação do campo chave id_aluno, só existe se, o seqüêncial não foi executado como DEFAULT, isso pelo uso de um valor incluído no INSERT ou UPDATE, e continua com o valor anterior no START. veja isso com o comando SELECT CURVAL('seq_alunos') entre aspas o seqüêncial após o NEXTVAL inicial...


Isso daí é o mais importante. Vou ver com carinho o NEXTVAL e CURVAL.

Muito obrigado pela ajuda! Aprendi e vou pôr em prática!
Grande abraço!!! :D
Responder
Fabiano, so para complementar a última resposta, se voce tiver uma tabela com muitos campos e nao quizer qualificar o insert tipo
Insert into alunos (nome, data_nasc) values (teste, ' 01/01/1980' ), voce pode usar a palavra chave default na posicao do campo que quer que isto ocorra
Ex. Insert into alunos values (' teste' , default, '01/01/1980') , com isso mesmo que o teu serial seja not null nao irá violar o constraint, e para campos sem valor default o banco ente como nulo !
Espero ter ajudado
Responder
Obrigado pela dica, Saulo! Vou anotá-la no meu txt de PostGreSQL!
Obrigado a todos!

Bom FDS!
Responder