Publicidade (Anuncie Aqui)

Cadastrando múltiplos registros no MySQL ao mesmo tempo

Cadastrando múltiplos registros no MySQL ao mesmo tempo

Hoje vou falar sobre uma pequena mudança de código que pode significar megas e megas de dados e, conseqüentemente, de performance! :D

Suponhamos que você tenha um script que receba dados de sei lá onde e cadastre-os no MySQL, seria mais ou menos assim:

<?php

$usuarios = array();
$usuarios[] = array('nome' => 'Thiago', 'email' => 'contato@thiagobelem.net');
$usuarios[] = array('nome' => 'Fulano da Silva', 'email' => 'fulano@email.com');
$usuarios[] = array('nome' => 'Ciclano', 'email' => 'ciclano@uol.com.br');

// Inicia a variável
$cadastrados = 0;

// Para cada elemento de $usuários, faça:
foreach ($usuarios as $usuario) {
	$nome = $usuario['nome'];
	$email = $usuario['email'];

	// Monta a consulta
	$sql = "INSERT INTO `usuarios` (`id`, `nome`, `email`) VALUES (NULL, '{$nome}', '{$email}');";

	// Executa a consulta verificando se foi inserido com sucesso
	if (mysql_query($sql)) {
		// Incrementa o contador
		$cadastrados++;
	}
}

echo 'Usuários cadastrados: ' . $cadastrados;

?>

As consultas passadas para o MySQL ficariam mais ou menos assim:

INSERT INTO `usuarios` (`id`, `nome`, `email`) VALUES (NULL, 'Thiago', 'contato@thiagobelem.net');
INSERT INTO `usuarios` (`id`, `nome`, `email`) VALUES (NULL, 'Fulano da Silva', 'fulano@email.com');
INSERT INTO `usuarios` (`id`, `nome`, `email`) VALUES (NULL, 'Ciclano', 'ciclano@uol.com.br');

Não tem nada de errado com o código.. Funciona perfeitamente… Faz o contador direitinho.. Mas imagine se você tem 4000 registros pra inserir na tabela… Você vai rodar 4000 mysql_query() e vai deixar o seu MySQL maluquinho!

Não seria muito melhor fazer assim:

<?php

$usuarios = array();
$usuarios[] = array('nome' => 'Thiago', 'email' => 'contato@thiagobelem.net');
$usuarios[] = array('nome' => 'Fulano da Silva', 'email' => 'fulano@email.com');
$usuarios[] = array('nome' => 'Ciclano', 'email' => 'ciclano@uol.com.br');

// Início da consulta
$sql = "INSERT INTO `usuarios` (`id`, `nome`, `email`) VALUES";

// Para cada elemento de $usuários, faça:
foreach ($usuarios as $usuario) {
	$nome = $usuario['nome'];
	$email = $usuario['email'];

	// Monta a parte consulta de cada usuário
	$sql .= " (NULL, '{$nome}', '{$email}'),";
}

// Tira o último caractere (vírgula extra)
$sql = substr($sql, 0, -1);

// Executa a consulta
mysql_query($sql);

// Pega o número de registros inseridos
$cadastrados = mysql_affected_rows();

echo 'Usuários cadastrados: ' . $cadastrados;

?>

A nossa consulta ficaria mais ou menos assim:

INSERT INTO `usuarios` (`id`, `nome`, `email`) VALUES (NULL, 'Thiago', 'contato@thiagobelem.net'), (NULL, 'Fulano da Silva', 'fulano@email.com'), (NULL, 'Ciclano', 'ciclano@uol.com.br')

Você pode fazer isso sem problema nenhum e com apenas uma “execução de consulta” você insere os três registros de uma só vez… Não é uma maravilha? :D

Você também vai gostar de ler:

Postado em Artigos, MySQL, PHP, Tutoriais

Com as tags , , , , , , , , , , ,

Escrito por Thiago Belem

Gostou desse artigo?

Não se esqueça de assinar o RSS e divulgue-o para o mundo:

  • Gilmar Angelo
    Silvio

    Com a função mysql_insert_id(), você pega o ultimo registro increment gerado.

    Abraço
  • Silvio
    Gilmar,

    com está função eu pego o último id inserido. Eu gostaria de pegar os últimos id´s que foram inseridos, no exemplo do blog é inserido na base de dados 3 registro "ao mesmo tempo", eu gostaria de pegar o id gerado para cada um.

    abrá
  • Olá,
    gostaria de saber como eu faço para pegar o id de cada item que foi inserido neste seu exemplo.
    abrços.
  • O que vc pode fazer seria realizar uma contagem do ultimo id que esta em seu banco de dados, vamos supor que seja 50, então vc sabe que ele vai começar no 51, então vc pode utilizar um funcão do php para tratamento de array, e contar o numero de registros, assim você pode dizer que o registro numero 1 do array e no numero 51 do banco de dados, e assim sucessivamente, so que este tipo de script, teria de realizar uma exportação para uma outra tabela, ou para um arquivo de texto, xls. espero ter ajudado.
  • @Júlio
    Tome cuidado... O fato do último ID da tabela ser 50 ou a tabela conter 50 registros não significa que o próximo ID será 51. O auto_increment existe... Podemos ter uma tabela vazia e o "próximo ID" poderia ser 83.
  • @Silvio
    Não há uma forma simples de fazer isso.. Você precisaria fazer um SELECT depois.
  • _Dudu_1533
    Ótimo, parabéns!
  • Francis
    Muito bom! Mas gostaria de saber se funciona tambem para o comando UPDATE? E como ficaria o código?
  • Danilo Miguel
    Thiago,
    Parabéns pelo trabalho realizado aqui no seu blog. Acabei de conhecer e já dei uma geral em quase todos os textos. Muito bom mesmo!

    Como você respondeu para o Sergio, seria interessante sim fazer a quebra das inserções. Diria até obrigatório, no caso de inserções monstruosas.

    O que acha de dar uma "soneca" para o servidor também, com sleep()? Ou seja, insere mil, "dorme", insere mais mil e assim por diate. Como ficaria esse código?

    Ah, mais ainda: como ficaria isso no CakePHP, que tem suas instruções padronizadas? O negócio seria fugir do padrão?

    Sucesso cada vez maior!
  • @Danilo
    É bom sim pausar o script, pode usar um sleep mesmo depois de uma cadeia grande de INSERTS... :)
  • Fillipe
    Mais uma dica muito útil que já utilizei no meu sistema!

    Vlw
  • Sergio
    Blz boy, mas assim, não teria o perigo (em pedidos super-mega-master-blaster gigantes) de um travamento do MySQL, com string's ultra gigantes? ou talvez, estourar o tamanho da string, dar uma sobrecarga no servidor, chove granizo em Sergipe, sei la, não seria melhor tipo limitar essas super-pesquisas em pacotes de tamanho limitado (como por exemplo em pacotes de até 3.000)???
    Flw, mt boa dica.
  • @Sergio
    Sim.. Quanto a isso você está certo... Seria bom quebrar a cada 1000 inserções mais ou menos. :)
  • MAAARA.
blog comments powered by Disqus