[Resolvido]Dúvida com SQL e auto_increment

Olá!!

Tenho uma dúvida que acredito ser bem infeliz e simples,
Fiz uma aplicação Java Swing que conecta à um banco de dados MySQL. O aplicativo por enquanto está em Core e simplesmente grava algumas informações no banco (como ainda não fiz a parte de leitura, eu visualizo apenas no terminal do MySQL)
Minha tabela é:

| FIELD | Type | Null | Key | Default | Extra |


| id | int(11) | NO | PRI | NULL | auto_increment |
| nome | varchar(30) | NO | | NULL | |
| sobrenome | varchar(30) | NO | | NULL | |
| telefone | varchar(30) | YES | | NULL | |

Como pode ver, o campo id é auto_increment, então, teoricamente, ele se completaria automaticamente à cada nova Inserção, mas isso não acontece, eu sou obrigado a informar um id na hora de executar a query ou recebe um erro informado que o número de Values é diferente do número de colunas.

[code]PreparedStatement stmt = conn.prepareStatement( "INSERT INTO trabalho VALUES (?,?,?,?) ");

		stmt.setInt(1, id);
		stmt.setString(2, nome);
		stmt.setString(3, sobrenome);
		stmt.setString(4, telefone);
		
		stmt.execute();
		stmt.close();[/code]

Será que não estou sabendo usar o Id com auto_increment? ou errei na hora de criar a tabela? estranho porque eu já tinha feito isso quando trabalhei com PHP e isso não acontecia…
Att,
Eduardo

Se o id ta configurado pra auto increment pode rancar ele fora aí do statement, começa pelo nome…

[code] PreparedStatement stmt = conn.prepareStatement( "INSERT INTO trabalho VALUES (?,?,?) ");

            stmt.setString(1, nome); [/code]

O problema não é o auto_increment, nem o banco de dados.
O problema é que você diz ao PreparedStatement que ele receberá quatro argumentos. Se você alterar teu código para

PreparedStatement stmt = conn.prepareStatement( "INSERT INTO trabalho (col1, col2, col3) VALUES (?,?,?) ");  
              
            stmt.setString(1, nome);  
            stmt.setString(2, sobrenome);  
            stmt.setString(3, telefone);  
              
            stmt.execute();  
            stmt.close();  

Provavelmente resolva.
Lembre-se de incluir as colunas que receberão os parâmetros.

Hm…

Achei que uso dos argumentos não fosse obrigatório, se não me engano já li em algum lugar que caso eles não sejam indicados na query os valores serão adiconados na tabela na ordem em que forem passados…

[quote=tunai]Hm…

Achei que uso dos argumentos não fosse obrigatório, se não me engano já li em algum lugar que caso eles não sejam indicados na query os valores serão adiconados na tabela na ordem em que forem passados…[/quote]
Sim, o problema é que você nunca sabe onde a ordenação coloca a PK.
Peque pelo excesso, nunca pela falta.

[quote=tunai]Hm…

Achei que uso dos argumentos não fosse obrigatório, se não me engano já li em algum lugar que caso eles não sejam indicados na query os valores serão adiconados na tabela na ordem em que forem passados…[/quote]

Exatamente, as colunas não são obrigatórias, caso não tenha argumentos ele insere na ordem passada…

Mas drsmachado, Indo diretamente no terminal do MySQL e utilizando a Query:
"INSERT INTO trabalho VALUES ( ‘exemploNome’, ‘exemploSobreNome’, ‘exemploTelefone’)"
ele retorna o erro Column count doesn’t match value count at row 1
só funciona se a Query seguir esse padrão:
“INSERT INTO trabalho VALUES ( 8, ‘exemploNome’, ‘exemploSobreNome’, ‘exemploTelefone’)” , onde 8 assume o valor do ID (que deveria ser preenchido automaticamente)

Tentou da forma como eu recomendei, determinando quais são as colunas a serem alteradas?

Tentei sim, no caso ficou:

[code]try {

		PreparedStatement stmt = conn.prepareStatement( "INSERT INTO trabalho (nome, sobrenome, telefone) VALUES (?,?,?) ");
		
		//stmt.setInt(1, id);
		stmt.setString(2, nome);
		stmt.setString(3, sobrenome);
		stmt.setString(4, telefone);
		
		stmt.execute();
		stmt.close();
		
		suc = true;
		
	} catch (SQLException e) {
		
		suc = false;
	}

[/code]

Onde a variável suc informa se foi gravado com sucesso ou não, como ela retornou false, a query não foi executada.
Informando os quatros campos (id, nome, sobrenome e telefone) ela retorna true

Olha como voce colocou:

Na verdade você começa do 1

stmt.setString(1, nome); stmt.setString(2, sobrenome); stmt.setString(3, telefone);

[quote=Yelden]Tentei sim, no caso ficou:

[code]try {

		PreparedStatement stmt = conn.prepareStatement( "INSERT INTO trabalho (nome, sobrenome, telefone) VALUES (?,?,?) ");
		
		//stmt.setInt(1, id);
		stmt.setString(2, nome);
		stmt.setString(3, sobrenome);
		stmt.setString(4, telefone);
		
		stmt.execute();
		stmt.close();
		
		suc = true;
		
	} catch (SQLException e) {
		
		suc = false;
	}

[/code]

Onde a variável suc informa se foi gravado com sucesso ou não, como ela retornou false, a query não foi executada.
Informando os quatros campos (id, nome, sobrenome e telefone) ela retorna true

[/quote]
Teu código tem dois erros grotescos.
O primeiro foi apontado pelo tunai.
O segundo é que você não trata a exceção, apenas coloca a tua variável suc como false. Isso é bizarramente errado.
Toda exceção deve ser tratada, exibida e analisada.

Tem razão tunai, eu sub-entendi que a linha 1 seria a primeira linha de inserção.

Agora consegui gravar com sucesso sem informar o ID, porém, uma última dúvida: por exemplo:
porque esse Query não funcionou? :
"INSERT INTO trabalho VALUES ( ‘exemploNome’, ‘exemploSobreNome’, ‘exemploTelefone’)"
como eu montaria esta query para inserir dados sem especificar as colunas? Ou Melhor, Como eu digo para o MySQL que a coluna ID é incrementada automaticamente? qual parametro eu devo colocar para informar isso?

Obrigado pela ajuda!

[quote=drsmachado][quote=Yelden]Tentei sim, no caso ficou:

[code]try {

		PreparedStatement stmt = conn.prepareStatement( "INSERT INTO trabalho (nome, sobrenome, telefone) VALUES (?,?,?) ");
		
		//stmt.setInt(1, id);
		stmt.setString(2, nome);
		stmt.setString(3, sobrenome);
		stmt.setString(4, telefone);
		
		stmt.execute();
		stmt.close();
		
		suc = true;
		
	} catch (SQLException e) {
		
		suc = false;
	}

[/code]

Onde a variável suc informa se foi gravado com sucesso ou não, como ela retornou false, a query não foi executada.
Informando os quatros campos (id, nome, sobrenome e telefone) ela retorna true

[/quote]
Teu código tem dois erros grotescos.
O primeiro foi apontado pelo tunai.
O segundo é que você não trata a exceção, apenas coloca a tua variável suc como false. Isso é bizarramente errado.
Toda exceção deve ser tratada, exibida e analisada.[/quote]

Exatamente drsmachado, mas como eu disse, é apenas um core, depois irei fazer o refactor, tratar as exceções… a intenção era só informar se a query foi executada ou não.
Eu costumo programar assim, faço um modelo bruto e simples, para depois trabalhar em cima dele, acho mais fácil…

Mesmo que seja apenas um rascunho. Se você tivesse tratado a exceção, teria visto que os índices dos parâmetros estava errada e, provavelmente, concluísse que era devido ao índice 4, que não existe.

É exatamente aí que está minha dúvida!!
O índice 4 existe sim! tanto que na Query “INSERT INTO trabalho VALUES ( ‘exemploNome’, ‘exemploSobreNome’, ‘exemploTelefone’)” ele retorna o erro que o número de colunas não bate com o número de valores, porque existem 4 colunas e estou passado apenas 3 valores. Sendo que a coluna ID é auto_increment, logo ele deveria considerar os 3 valores que eu passei, e somar com o valor automatico do Id, resultando em 4 valores para 4 colunas, entendeu o que eu quis dizer?

Você está falando de uma coisa, pensando em outra.
O índice ao qual eu me refiro é referente aos parâmetros do PreparedStatement.
Se você possui 3 pontos de interrogação, os índices dos parâmetros vão de 1 a 3 (não sei por que raios o maldito programador não começou a contagem com zero).

Pois é, estou pensando à nível SQL,
O código PreparedStatement stmt = conn.prepareStatement( "INSERT INTO trabalho (nome, sobrenome, telefone) VALUES (?,?,?) ");
Transforma-se em uma Query, onde os Três pontos de interrogação são nome, sobrenome e telefone: stmt.setString(1, nome); stmt.setString(2, sobrenome); stmt.setString(3, telefone);
Mas, no console do MySQL, ele exige que o campo Id seja informado no Values, caso eu não especifique as colunas.

Mas agradeço a ajuda, o Id está se incrementando, por hora está excelente, vou estudar mais sobre e SQL, isso deve ser coisa básica.

Vou marcar como resolvido, Obrigado!

[quote=Yelden]Pois é, estou pensando à nível SQL,
O código PreparedStatement stmt = conn.prepareStatement( "INSERT INTO trabalho (nome, sobrenome, telefone) VALUES (?,?,?) ");
Transforma-se em uma Query, onde os Três pontos de interrogação são nome, sobrenome e telefone: stmt.setString(1, nome); stmt.setString(2, sobrenome); stmt.setString(3, telefone);
Mas, no console do MySQL, ele exige que o campo Id seja informado no Values, caso eu não especifique as colunas.

Mas agradeço a ajuda, o Id está se incrementando, por hora está excelente, vou estudar mais sobre e SQL, isso deve ser coisa básica.

Vou marcar como resolvido, Obrigado![/quote]
O problema é que, quando você não especifica o que está inserindo numa tabela do MySQL, ele irá assumir que você está inserindo TODOS os dados, independente da coluna ser um PK auto_increment. Ele só incrementa ou define valores para colunas que são PK e, portanto, podem ser auto_increment ou para colunas com default value definidos, porém, você precisa, para todas as demais, dizer, explicitamente, que valores estão sendo inseridos e em quais colunas são inseridos. O MySQL não pode adivinhar o que você quer fazer.