Duplicação de Primary Key

9 respostas
F

Fala galera, estava procurando um tópico sobre este problema, achei, mais o cara conseguiu resolver, mais não postou a resolução, o meu eh bem parecido com o dele… estou fazendo uma aplicação em java, e estou com problemas em chave duplicada, ou seja, esse erro --> Duplicate entry ‘18’ for key ‘PRIMARY’ 18, eh a id que está tentando inserir dois tipos de produtos ao mesmo tempo, fala que a venda foi cadastrada com sucesso, mais gera essa exceção…

com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry 18 for key PRIMARYat sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)

at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)

at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)

O meu código da minha classe Vendas:

public class VendasControl {

PreparedStatement pst;
ResultSet rs;

String cadastraVenda = “INSERT INTO VENDAS (ID_VENDAS, ID_PRODUTOS, ID_ALUNOS, DATA_VENDAS, QUANTIDADE) "
+ " VALUES (?,?,?,?,?)”;

String buscaUltimoCodigo = “SELECT MAX(ID_VENDAS) AS ID_VENDAS FROM VENDAS”;

public VendasControl(){

}

public int buscarCodigoUltimaVenda(){

try{

ConexaoBD bd = new ConexaoBD();

pst = (PreparedStatement) bd.conectar().prepareStatement(buscaUltimoCodigo);

rs = pst.executeQuery();

if (rs.last()){

return rs.getInt(id_vendas);

}

bd.desconectar();

} catch (SQLException ex){

ex.printStackTrace();

}

return 0;

}

public void CadastrarVenda(VendasBean venda){

try{
ConexaoBD bd = new ConexaoBD();
pst = (PreparedStatement) bd.conectar().prepareStatement(cadastraVenda);
pst.setInt(1, venda.getId());
pst.setInt(2, venda.getIdProduto());
pst.setInt(3, venda.getIdAluno());
pst.setDate(4, venda.getDataVenda());
pst.setInt(5, venda.getQuantidade());
pst.executeUpdate();
bd.desconectar();
}catch (SQLException ex){
    ex.printStackTrace();
}

}

}

Código que cadastra a venda:

private void cadastrarVenda(){

if(venda.size() == 0){

JOptionPane.showMessageDialog(this, Inclua pelo menos um produto!);
}else{
        try{
        VendasControl vc = new VendasControl();
        SimpleDateFormat formato = new SimpleDateFormat("yyyy-MM-dd"); //formata o campo para datas
        java.util.Date d = new java.util.Date();
        Date data = Date.valueOf(formato.format(d)); //data da venda
        int codigo = vc.buscarCodigoUltimaVenda() + 1;
        for (int i = 0; i < venda.size(); i++){
            venda.get(i).setIdAluno(alunos.get(cbAlunos.getSelectedIndex()).getId());
            venda.get(i).setDataVenda(data);
            venda.get(i).setId(codigo);
            vc.CadastrarVenda(venda.get(i));
        }
         JOptionPane.showMessageDialog(this, "Venda cadastrada com sucesso!");
        }catch (Exception ex){
            JOptionPane.showMessageDialog(this, "Erro ao cadastrar Venda!");
        }
    }
}

Aqui a imagem do que eu to falando !

http://img171.imageshack.us/img171/913/print6lu.png

Quando eu clico em finalizar, é quando gera esse erro que eu falei acima !
Obs: Não importa o produto, pode ser de nome diferente, id diferente, se eh dois ou mais, da esse erro, agora se for um produto, nem gera erro e vai de booa !

Agradeço desde já quem puder me ajudar ! Obrigado e até mais :slight_smile:

9 Respostas

A

Meu amigo Bom dia,

Esse problema vc resolve colocando auto_incremente no campo de id, e não o colocando no corpo do insert.

F

Cooomo assim, não entendi… ele ta como auto increment la no banco sql.

Código SQL:

create table vendas(

id_vendas int default null,
id_produtos int (50) default null,
id_alunos int (25) default null,
Data_vendas DATE default null,
quantidade int (10) default null,
primary key (id_vendas)
);
ALTER TABLE vendas ADD CONSTRAINT fk_id_produtos
FOREIGN KEY ( id_produtos )
REFERENCES produtos (id_produto) ;

ALTER TABLE vendas ADD CONSTRAINT fk_id_alunos
FOREIGN KEY ( id_alunos )
REFERENCES alunos (id) ;

ALTER TABLE vendas MODIFY id_vendas int NULL AUTO_INCREMENT;

A

Se o campo estiver como Auto Increment, você pode suprimí-lo de seu INSERT.

De qualquer forma, recomendo que procure na internet sobre os problemas de se usar select max() para fazer geração de incremento de PK.

Abraços,

A

Quando vc coloca auto increment no PK, vc diz para o Banco cuidar de administrar a PK…

No insert não coloca ID_VENDAS

String cadastraVenda = “INSERT INTO VENDAS (ID_PRODUTOS, ID_ALUNOS, DATA_VENDAS, QUANTIDADE) " + " VALUES (?,?,?,?)”;

Obs.: para retornar o resultado PK faça o fonte abaixo, gerar select max com vários usuários pode ocasionar erro, pois não garante que o ultimo inserido foi o que vc inseriu.

PreparedStatement stmt = conn.prepareStatement(cadastraVenda);
        stmt.executeUpdate(sql, Statement.RETURN_GENERATED_KEYS);
        ResultSet rs = stmt.getGeneratedKeys();
        int pk = 0;
        if (rs.next()) {
            pk = rs.getInt(1);
        }
        stmt.close();
F

Valew pela ajudaaa galera, mais agora o erro é este aqui --> om.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘?,?,?,?)’ at line 1

F

O que está acontecendo, imagino eu, é que a chave primária refere-se apenas ao ID_VENDAS.
Quando vai alocar um segundo produto utiliza (logicamente) o mesmo ID_VENDAS, violando a constraint.

Nesse caso, pode modificar a chave primária para que seja composta por outros IDS. mais nem sei como qe faz isso…

bom, isso é o que eu penso !

C

A tabela que você criou não tem muito sentido… do jeito que vc fez, você só vai poder ter 1 produto por venda, a menos que o id_produto fosse chave também…

Crie duas tabelas para o modelo ficar bem mais bonito… uma tabela VENDA e outra VENDA_PRODUTO por exemplo

Na VENDA você coloca as informações básicas, como: ID_VENDA, ID_ALUNO, DATA etc… e na tabela VENDA_PRODUTO você coloca ID_VENDA, ID_PRODUTO, QUANTIDADE etc… Seu modelo fica muito mais elegante.

A

Olá novamente,

seguinte vc não colocou todo o log do problema, entao vou chutar uma possível solução:

Primeiro uma chave primaria pode ser composta por 1 ou N identificadores sim, o que diferencia chave primária e que ela é única exclusivamente isso.
Não entendi o que vc falou que pode estar violando constat … Mas com certeza não é isso. Notei que sua PK é int e por default ela é null ?? (nunca um identificador PK é null).

A parte que eu chuto ser o erro é:

String cadastraVenda = "INSERT INTO VENDAS (ID_PRODUTOS, ID_ALUNOS, DATA_VENDAS, QUANTIDADE) " + " VALUES (?,?,?,?)"; 

// pst.setInt(1, venda.getId());  Sem isso ID_VENDAS
pst.setInt(1, venda.getIdProduto()); 
pst.setInt(2, venda.getIdAluno()); 
pst.setDate(3, venda.getDataVenda()); 
pst.setInt(4, venda.getQuantidade());
F

E ae pessoal, eu consegui resolver o problema, o problema era na minha tabela do MySQL

ANTES:

create table vendas(

id_vendas int default null,

id_produtos int (50) default null,

id_alunos int (25) default null,

Data_vendas DATE default null,

quantidade int (10) default null,

primary key (id_vendas)

);

DEPOIS:

create table vendas(

id_vendas int default null,

id_produtos int (50) default null,

id_alunos int (25) default null,

Data_vendas DATE default null,

quantidade int (10) default null,

primary key (id_vendas, id_produtos)

);

ou seja, esqeci de colocar o id_produtos de pk tbm, pois a chave primária tinha que ser composta por outros IDS.

mas agora, ta dando o seguinte erro: Duplicate entry ‘14-28’ for key ‘PRIMARY’

ou seja, ele nao ta aceitando dois produtos de mesmo nome pra um mesmo aluno…

o código que inclui o produto é esse:

private void incluirProduto(){

if (verificarQuantidade()){

VendasBean vb = new VendasBean();

vb.setIdProduto(produtos.get(cbProdutos.getSelectedIndex()).getId());

vb.setQuantidade(Integer.parseInt(String.valueOf(ftfQuantidade.getValue())));

venda.add(vb);

String produto = produtos.get(cbProdutos.getSelectedIndex()).getNome();

String quantidade = String.valueOf(ftfQuantidade.getValue());

String valor = String.valueOf(produtos.get(cbProdutos.getSelectedIndex()).getValor() * Integer.parseInt(quantidade));

String [] campos = new String [] {produto, quantidade, valor};

tmVendas.addRow(campos);

total += Double.parseDouble(valor);

ftfTotal.setValue(total);
}else{
        JOptionPane.showMessageDialog(this, "Quantidade inválida!");
        ftfQuantidade.requestFocus();
    }         
    
}

porém não to sabendo definir uma lógica, que pra quando eu inserir um produto, ex: Whey, ai eu vou tentar inserir outro, de mesmo nome Whey, ele da uma msg, dizendo que não é possivel adc 2 ou mais produtos de mesmo nome pra um mesmo aluno, o produto tem que ser distinto !

Obrigado pela ajuda de todos até agora ! Agradeço desde já ! Boa Tarde !

Criado 27 de fevereiro de 2013
Ultima resposta 28 de fev. de 2013
Respostas 9
Participantes 5