Inserir tabela MySql se não existir, caso contrário, atualizar

105
UPDATE AggregatedData SET datenum="734152.979166667", 
Timestamp="2010-01-14 23:30:00.000" WHERE datenum="734152.979166667";

Funciona se datenumexistir, mas quero inserir esses dados como uma nova linha se datenumnão existir.

ATUALIZAR

o datenum é único, mas essa não é a chave primária

OHLÁLÁ
fonte
2
O "datenum" é único? Você pode usar INSERT ... ON DUPLICATE KEY UPDATE se for.
Jacob

Respostas:

143

Jai está correto que você deve usar INSERT ... ON DUPLICATE KEY UPDATE.

Observe que você não precisa incluir o datenum na cláusula de atualização, pois é a chave exclusiva, portanto, não deve ser alterado. Você precisa incluir todas as outras colunas de sua tabela. Você pode usar a VALUES()função para garantir que os valores adequados sejam usados ​​ao atualizar as outras colunas.

Aqui está sua atualização reescrita usando a INSERT ... ON DUPLICATE KEY UPDATEsintaxe apropriada para MySQL:

INSERT INTO AggregatedData (datenum,Timestamp)
VALUES ("734152.979166667","2010-01-14 23:30:00.000")
ON DUPLICATE KEY UPDATE 
  Timestamp=VALUES(Timestamp)
Ike Walker
fonte
18
Tenha cuidado ao usar INSERT ... ON DUPLICATE KEY UPDATE em tabelas em relação a uma tabela que tem mais de uma chave única ou primária. Retirado da documentação do MySQL : Além disso, a partir do MySQL 5.5.24, uma instrução INSERT ... ON DUPLICATE KEY UPDATE em uma tabela com mais de uma chave única ou primária também é marcada como insegura. (Bug # 11765650, Bug # 58637) Descrição do Bug 58637 bugs.mysql.com/bug.php?id=58637
banda larga
1
Pode ser necessário criar uma UNIQUErestrição TimestampusandoALTER TABLE AggregatedData ADD UNIQUE (Timestamp)
Avyakt
@broadband você pode usar uma chave composta para evitar este bug
Kareem
16

Tente usar este :

Se você especificar ON DUPLICATE KEY UPDATE, e uma linha for inserida, isso causará um valor duplicado em uma UNIQUE index orPRIMARY KEY , MySQL performs an [UPDATE`] ( http://dev.mysql.com/doc/refman/5.7/en/update.html ) da linha anterior. ..

A ON DUPLICATE KEY UPDATEcláusula pode conter várias atribuições de coluna, separadas por vírgulas.

Com ON DUPLICATE KEY UPDATE, o valor de linhas afetadas por linha é 1 se a linha for inserida como uma nova linha, 2 se uma linha existente for atualizada e 0 se uma linha existente for definida com seus valores atuais. Se você especificar o CLIENT_FOUND_ROWSsinalizador para mysql_real_connect()ao conectar-se ao mysqld , o valor de linhas afetadas é 1 (não 0) se uma linha existente é definida com seus valores atuais ...

Jai
fonte
Mas meu datenum não é a chave primária.
OHLÁLÁ
Então no meu caso qual é a solução, eu tentei esta, sem nenhuma solução: INSERT INTO forwind.aggregateddata (datenum, Timestamp, Min_F1_baro_20_) VALUES ('1', '2', '3') ON DUPLICATE KEY UPDATE datenum = datenum;
OHLÁLÁ
1
o datenum é suposto ser único? em caso afirmativo, adicione um índice exclusivo a ele (se ainda não tiver sido adicionado). Então, ele funcionará. Consulte dev.mysql.com/doc/refman/5.1/en/alter-table.html para saber como anunciar índices UNIQUE
Jai
agora eu defini o datenum como único e está funcionando bem, obrigado
OHLÁLÁ
1
Apenas um link, talvez dê uma resposta.
Andrew
0

Tive uma situação em que precisei atualizar ou inserir em uma tabela de acordo com dois campos (ambas as chaves estrangeiras) em que não consegui definir uma restrição UNIQUE (então INSERT ... ON DUPLICATE KEY UPDATE não funcionou). Aqui está o que acabei usando:

replace into last_recogs (id, hasher_id, hash_id, last_recog) 
  select l.* from 
    (select id, hasher_id, hash_id, [new_value] from last_recogs 
     where hasher_id in (select id from hashers where name=[hasher_name])
     and hash_id in (select id from hashes where name=[hash_name]) 
     union 
     select 0, m.id, h.id, [new_value] 
     from hashers m cross join hashes h 
     where m.name=[hasher_name] 
     and h.name=[hash_name]) l 
  limit 1;

Este exemplo foi extraído de um de meus bancos de dados, com os parâmetros de entrada (dois nomes e um número) substituídos por [hasher_name], [hash_name] e [new_value]. O SELECT ... LIMIT 1 aninhado puxa o primeiro do registro existente ou um novo registro (last_recogs.id é uma chave primária de incremento automático) e usa isso como o valor de entrada no REPLACE INTO.

salfter
fonte
REPLACE sempre insere uma nova linha! ele apenas apaga o original, já existente!
jasie de