Comecei pesquisando no Google e encontrei este artigo que fala sobre tabelas mutex.
Eu tenho uma mesa com ~ 14 milhões de registros. Se eu quiser adicionar mais dados no mesmo formato, existe uma maneira de garantir que o registro que desejo inserir ainda não exista sem o uso de um par de consultas (por exemplo, uma consulta para verificar e outra para inserir é o conjunto de resultados) esvaziar)?
Uma unique
restrição em um campo garante que a insert
falha falhe se já estiver lá?
Parece que, com apenas uma restrição, quando emito a inserção via php, o script resmunga.
mysql
sql
primary-key
sql-insert
Warren
fonte
fonte
Respostas:
usar
INSERT IGNORE INTO table
consulte http://bogdan.org.ua/2007/10/18/mysql-insert-if-not-exists-syntax.html
também há
INSERT … ON DUPLICATE KEY UPDATE
sintaxe, você pode encontrar explicações em dev.mysql.comPublique em bogdan.org.ua de acordo com o webcache do Google :
fonte
INSERT … ON DUPLICATE KEY UPDATE
é melhor, pois não exclui a linha, preservando quaisquerauto_increment
colunas e outros dados.INSERT … ON DUPLICATE KEY UPDATE
método using incrementa qualquer coluna AUTO_INCREMENT com falha na inserção. Provavelmente porque realmente não falhou, mas atualizou.Solução:
Explicação:
A consulta mais interna
usado como a
WHERE NOT EXISTS
condição detecta se já existe uma linha com os dados a serem inseridos. Depois que uma linha desse tipo é encontrada, a consulta pode parar e, portanto, aLIMIT 1
(micro otimização pode ser omitida).A consulta intermediária
representa os valores a serem inseridos.
DUAL
refere-se a uma linha especial, uma tabela de coluna presente por padrão em todos os bancos de dados Oracle (consulte https://en.wikipedia.org/wiki/DUAL_table ). Em um servidor MySQL versão 5.7.26, recebi uma consulta válida ao omitirFROM DUAL
, mas versões mais antigas (como 5.5.60) parecem exigir asFROM
informações. UsandoWHERE NOT EXISTS
da consulta intermediária retorna um conjunto de resultados vazio se a consulta mais interna encontrar dados correspondentes.A consulta externa
insere os dados, se algum for retornado pela consulta intermediária.
fonte
INSERT IGNORE
eINSERT ON DUPLICATE KEY
exigem restrições de chave únicas)stuff for value1
estuff for value2
for idêntico? Isso daria umDuplicate column name
SELECT 1
do queSELECT *
nas subconsultas. Muito mais provável que isso possa ser satisfeito por um índice.na atualização de chave duplicada ou inserir ignorar pode ser soluções viáveis com o MySQL.
Exemplo de atualização de chave duplicada com base em mysql.com
Exemplo de inserção ignorar com base em mysql.com
Ou:
Ou:
fonte
Qualquer restrição simples deve fazer o trabalho, se uma exceção for aceitável. Exemplos :
Desculpe, isso parece enganosamente simples. Sei que parece ruim em relação ao link que você compartilha conosco. ;-(
Mas, mesmo assim, eu dou essa resposta, porque parece preencher sua necessidade. (Caso contrário, isso poderá desencadear a atualização de seus requisitos, o que seria "uma coisa boa" (TM) também).
Editado : se uma inserção quebrar a restrição exclusiva do banco de dados, uma exceção será lançada no nível do banco de dados, retransmitida pelo driver. Certamente interromperá o seu script, com uma falha. No PHP deve ser possível resolver esse caso ...
fonte
INSERT IGNORE
basicamente altera todos os erros em avisos para que seu script não seja interrompido. Você pode, então, visualizar todos os avisos com o comandoSHOW WARNINGS
. E outra nota importante : restrições UNIQUE não funcionam com valores NULL, ie. linha1 (1, NULL) e linha2 (1, NULL) serão inseridas (a menos que outra restrição, como uma chave primária, seja quebrada). Infeliz.Aqui está uma função PHP que inserirá uma linha apenas se todos os valores de colunas especificados ainda não existirem na tabela.
Se uma das colunas diferir, a linha será adicionada.
Se a tabela estiver vazia, a linha será adicionada.
Se existir uma linha em que todas as colunas especificadas tenham os valores especificados, a linha não será adicionada.
Exemplo de uso:
fonte
mysql_*
extensão está obsoleta no PHP 5.5.0 e foi removida no PHP 7.0.0. Em vez disso, a extensão mysqli ou PDO_MySQL deve ser usada. Consulte também a Visão geral da API do MySQL para obter mais ajuda ao escolher uma API do MySQL.Se o registro existir, ele será substituído; se ainda não existir, será criado.
fonte
REPLACE
pode excluir a linha e depois inserir em vez de atualizar. O efeito colateral é que as restrições podem excluir outros objetos e os gatilhos de exclusão são acionados.Tente o seguinte:
fonte
Existem várias respostas que abordam como resolver isso se você tiver um
UNIQUE
índice que possa ser verificado comON DUPLICATE KEY
ouINSERT IGNORE
. Esse nem sempre é o caso e, comoUNIQUE
possui uma restrição de comprimento (1000 bytes), talvez você não consiga alterar isso. Por exemplo, eu tive que trabalhar com metadados no WordPress (wp_postmeta
).Finalmente resolvi-o com duas consultas:
A consulta 1 é uma
UPDATE
consulta regular sem efeito quando o conjunto de dados em questão não está lá. A consulta 2 é umaINSERT
que depende de aNOT EXISTS
, ou seja,INSERT
é executada apenas quando o conjunto de dados não existe.fonte
Algo digno de nota é que o INSERT IGNORE ainda aumentará a chave primária, independentemente de a declaração ter sido bem-sucedida ou não, como um INSERT normal faria.
Isso causará lacunas nas chaves primárias que podem tornar um programador mentalmente instável. Ou se seu aplicativo for mal projetado e depender de chaves primárias incrementais perfeitas, poderá se tornar uma dor de cabeça.
Examine
innodb_autoinc_lock_mode = 0
(configuração do servidor e vem com um leve impacto no desempenho) ou use primeiro um SELECT para garantir que sua consulta não falhe (que também vem com um impacto no desempenho e código extra).fonte
SELECT
derrota, todo o objetivo de apenas entregar um lote grande de seINSERT
não querer se preocupar com duplicatas.Atualizar ou inserir sem chave primária conhecida
Se você já possui uma chave exclusiva ou primária, as outras respostas respondem com
INSERT INTO ... ON DUPLICATE KEY UPDATE ...
ouREPLACE INTO ...
devem funcionar bem (observe que substituir em exclusões, se existir, e depois inserir - portanto, não atualiza parcialmente os valores existentes).Mas se você tiver os valores para
some_column_id
esome_type
, cuja combinação é conhecida por ser única. E você deseja atualizar,some_value
se existir, ou inserir, se não existir. E você deseja fazer isso em apenas uma consulta (para evitar o uso de uma transação). Esta pode ser uma solução:Basicamente, a consulta é executada desta maneira (menos complicada do que parece):
WHERE
correspondência da cláusula.s
) em potencial , onde os valores da coluna são explicitamente fornecidos (s.id é NULL, portanto, ele gera um novo identificador de incremento automático).s
será descartada (devido a LIMIT 1 na tabelat
) e sempre acionará umaON DUPLICATE KEY
queUPDATE
asome_value
coluna.s
).Nota: Toda tabela em um banco de dados relacional deve ter pelo menos uma
id
coluna primária de incremento automático . Se você não tiver, adicione-o, mesmo quando não precisar dele à primeira vista. Definitivamente, é necessário para esse "truque".fonte
INSERT INTO ... SELECT FROM
formato. Por que você também?INSERT INTO... SELECT FROM...
solução regular . Consulte-me um link para uma resposta que seja a mesma; se você puder encontrá-la, eu excluirei esta resposta, caso contrário, você receberá minha resposta (oferta?). Verifique se a resposta que você vinculará usa apenas 1 consulta (para atualização + inserção), nenhuma transação e é capaz de segmentar qualquer combinação de colunas que sejam conhecidas por serem únicas (portanto, separadamente, as colunas não precisa ser único).