sakamoto 0 Denunciar post Postado Julho 20, 2012 Olá Senhores, Tenho uma determinada tabela com 10 colunas, preciso atualizar 01 coluna (estoque). Meu csv tem mais de 90.000 linhas contendo colunaID e colunaEstoque, preciso atualizar o que já existe (se o id existir ele altera a informacao do estoque) ou insere nova linha caso não encontre o id... como posso proceder pois o arquivo é muito pesado. Me informaram para fazer pausadamente... mas como fazer isso?1 Obrigado Compartilhar este post Link para o post Compartilhar em outros sites
Andrey Knupp Vital 136 Denunciar post Postado Julho 20, 2012 Poste as 10 primeiras linhas do seu arquivo para termos uma base. Compartilhar este post Link para o post Compartilhar em outros sites
sakamoto 0 Denunciar post Postado Julho 21, 2012 Perdão senhores, segue código usado atualmente (lembrando que ele funciona, consegui importar 500 linhas)... <?php include('../Lib/PHP/config.php'); $Importacao = array( 'Email' => 'email@cliente.com.br', // email para onde vai o relatorio 'Diretorio' => 'importar_estoque', // diretorio onde tem o arquivo a ser importado 'DiretorioLog' => 'relatorios', // diretorio onde será salvo o relatorio 'Tabela' => 'Produtos', // tabela que será utilizada 'SeparadorColunas' => ';', // tipo de separador 'Colunas' => array( 'ProdutoID', 'Estoque', ), // colunas a serem trabalhadas ); $ponteiro = opendir($Importacao["Diretorio"]); $itens = array(); // monta os vetores com os itens encontrados na pasta while ($nome_itens = readdir($ponteiro)) { if (($nome_itens != '.') && ($nome_itens != '..')) { $itens[] = $nome_itens; } } $IMPORTAR = array(); //Le e formata o arquivo para efetuar a importação dos dados foreach ($itens as $nome_arquivo) { if ($ARQUIVO = fopen($Importacao["Diretorio"] . '/' . $nome_arquivo, "r")) { $IMPORTAR[$nome_arquivo] = array( 'Importar' => array(), 'Erros' => array(), ); //Percorre todas as linhas do arquivo while(!feof($ARQUIVO)) { //Recebe o conteudo da linha atual if($CONTEUDO = fgets($ARQUIVO)) { //Separa as colunas da linha atual - utiliza a variavel de configuracao acima para saber qual caracter esta usando $CONTEUDOEXP = explode($Importacao["SeparadorColunas"],$CONTEUDO); //Se o tamanho do array de configuracao onde temos as colunas a serem atualizadas for igual ao total de colunas na linha do arquivo ele efetua os procedimentos de inclusao/alteracao, senao ele armazena o numero da linha com problemas para ao final informar o usuario if(sizeof($Importacao["Colunas"])==sizeof($CONTEUDOEXP)) { $count = 0; $linha = array(); $error = FALSE; foreach ($Importacao["Colunas"] as $coluna) { $linha[$coluna] = $CONTEUDOEXP[$count]; if (($coluna == 'ProdutoID') || ($coluna == 'GrupoID') || ($coluna == 'Cat') || ($coluna == 'SubCategoriaID') || ($coluna == 'Cat_SUB_SUB') || ($coluna == 'Cat_SUB_SUB_SUB') || ($coluna == 'MarcaID')) { $linha[$coluna] = (int)$linha[$coluna]; if (($coluna == 'ProdutoID') && ($linha[$coluna] <= 0)) { $IMPORTAR[$nome_arquivo]['Erros'][] = array('Linha' => $CONTEUDO, 'Motivo' => 'ProdutoID inválido.'); $error = TRUE; break; } } elseif (($coluna == 'DataCriacao') || ($coluna == 'DataAlteracao')) { list($dia, $mes, $ano) = explode('/', $linha[$coluna]); $temp = $mes . '/' . $dia . '/' . $ano; $linha[$coluna] = date('Y-m-d', strtotime($temp)) . ' 00:00:00'; unset($dia, $mes, $ano, $temp); } elseif ($coluna == 'Voltagem') { $linha[$coluna] = empty($linha[$coluna]) ? 'N' : $linha[$coluna]; } elseif (($coluna == 'Valor') || ($coluna == 'ValorDesconto')) { $linha[$coluna] = (float)$linha[$coluna]; $linha[$coluna] = number_format($linha[$coluna], 2, '.', ''); } $count++; } if (!$error) { $IMPORTAR[$nome_arquivo]['Importar'][] = array('Conteudo' => $CONTEUDO, 'Dados' => $linha); } } else { $IMPORTAR[$nome_arquivo]['Erros'][] = array('Linha' => $CONTEUDO, 'Motivo' => 'Numero de colunas da linha diferente das da tabela no banco.'); } } } fclose($ARQUIVO); } } //Le o array com infomacoes para importação, importa e gera arquivo de log. if (sizeof($IMPORTAR) > 0) { foreach ($IMPORTAR as $NOME_ARQUIVO => $DADOS) { if (sizeof($DADOS['Importar']) > 0) { foreach ($DADOS['Importar'] as $KEY_CONTEUDO => $CONTEUDO) { $SQL_UPDATE_WHERE = $Importacao["Colunas"][0] . "='" . recebe_dados($CONTEUDO['Dados'][$Importacao["Colunas"][0]]) . "'"; $SQL_CAMPOS_INSERT = ""; $SQL_VALUES_INSERT = ""; $SQL_UPDATE_VALUES = ""; $cont=-1; foreach ($CONTEUDO['Dados'] as $COLUNA => $VALOR) { $cont++; $SQL_CAMPOS_INSERT .= $COLUNA; $SQL_CAMPOS_INSERT .= ($cont < (sizeof($CONTEUDO['Dados'])-1)) ? "," : ""; $SQL_VALUES_INSERT .= "'" . recebe_dados($VALOR) . "'"; $SQL_VALUES_INSERT .= ($cont < (sizeof($CONTEUDO['Dados'])-1)) ? "," : ""; $SQL_UPDATE_VALUES .= $COLUNA . "='" . recebe_dados($VALOR) . "'"; $SQL_UPDATE_VALUES .= ($cont < (sizeof($CONTEUDO['Dados'])-1)) ? ", " : ""; } $SELECT = "SELECT 1 FROM ".$Importacao["Tabela"]." WHERE ".$SQL_UPDATE_WHERE; $RES = mysql_query($SELECT); if (!$RES) { $IMPORTAR[$NOME_ARQUIVO]['Erros'][] = array('Linha' => $CONTEUDO['Conteudo'], 'Motivo' => 'ProdutoID inválido.'); unset($IMPORTAR[$NOME_ARQUIVO]['Importar'][$KEY_CONTEUDO]); } else { if (mysql_num_rows($RES) > 0) { $SELECT = "UPDATE ".$Importacao["Tabela"]." SET ".$SQL_UPDATE_VALUES." WHERE ".$SQL_UPDATE_WHERE; $RES = mysql_query($SELECT); } else { $SELECT = "INSERT INTO ".$Importacao["Tabela"]."(".$SQL_CAMPOS_INSERT.") VALUES(".$SQL_VALUES_INSERT.")"; $RES = mysql_query($SELECT); } if (!$RES) { $IMPORTAR[$NOME_ARQUIVO]['Erros'][] = array('Linha' => $CONTEUDO['Conteudo'], 'Motivo' => 'Erro SQL ## Comando -> ' . $SELECT . ' ## Resposta -> ' . mysql_error() . '.'); unset($IMPORTAR[$NOME_ARQUIVO]['Importar'][$KEY_CONTEUDO]); } } } } } foreach ($IMPORTAR as $NOME_ARQUIVO_ => $DADOS) { $NOME_ARQUIVO = str_replace('.', '_', $NOME_ARQUIVO_) . '__LOGIMPORT__' . date('Y-m-d_H-i-s') . '.txt'; $quebra = chr(13).chr(10); //Gera conteudo para o arquivo de Log $CONTEUDO_ARQUIVO_LOG = 'Arquivo: ' . $NOME_ARQUIVO_ . $quebra; $CONTEUDO_ARQUIVO_LOG .= '===============================================' . $quebra; if (sizeof($DADOS['Importar']) > 0) { $CONTEUDO_ARQUIVO_LOG .= 'Registros importados com sucesso: ' . sizeof($DADOS['Importar']) . $quebra; } $CONTEUDO_ARQUIVO_LOG .= (sizeof($DADOS['Erros']) > 0) ? 'Registros não importados: ' . sizeof($DADOS['Erros']) . $quebra : 'Nenhum erro encontrado.' . $quebra; $CONTEUDO_ARQUIVO_LOG .= '===============================================' . $quebra . $quebra; foreach ($DADOS['Erros'] as $DADOS_LINHA) { $CONTEUDO_ARQUIVO_LOG .= 'Linha => ' . $DADOS_LINHA['Linha'] . $quebra; $CONTEUDO_ARQUIVO_LOG .= 'Motivo => ' . $DADOS_LINHA['Motivo'] . $quebra . $quebra . '--' . $quebra . $quebra; } //Cria arquivo de log no servidor $fp = fopen($Importacao['DiretorioLog'] . '/' . $NOME_ARQUIVO, 'a'); $escreve = fwrite($fp, $CONTEUDO_ARQUIVO_LOG); fclose($fp); //Envia email com log if (!empty($Importacao['Email'])) { $emailsender = (eregi('tempsite.ws$|locaweb.com.br$|hospedagemdesites.ws$|websiteseguro.com$', $_SERVER[HTTP_HOST])) ? 'webmaster@cliente.com.br' : "webmaster@" . $_SERVER[HTTP_HOST]; $quebra_linha = (PATH_SEPARATOR == ";") ? "\r\n" : "\n"; $nomeremetente = "Cliente"; $emailremetente = $emailsender; $comcopia = $Importacao['Email']; $assunto = "Importação de dados - " . $NOME_ARQUIVO; $headers = "MIME-Version: 1.1" .$quebra_linha; $headers .= "Content-type: text/html; charset=iso-8859-1" .$quebra_linha; $headers .= "From: ".$nomeremetente ." <" . $emailremetente.">".$quebra_linha; $headers .= "Cc: " . $comcopia . $quebra_linha; $headers .= "Bcc: " . $comcopiaoculta . $quebra_linha; $headers .= "Reply-To: " . $emailremetente . $quebra_linha; if (!mail($Importacao['Email'], $assunto, str_replace($quebra, '<br>', $CONTEUDO_ARQUIVO_LOG), $headers ,"-r".$emailsender)) { // Se for Postfix $headers .= "Return-Path: " . $emailsender . $quebra_linha; // Se "não for Postfix" mail($Importacao['Email'], $assunto, str_replace($quebra, '<br>', $CONTEUDO_ARQUIVO_LOG), $headers); } } unlink($Importacao["Diretorio"] . '/' . $NOME_ARQUIVO_); } print 'Dados importados - Revise os arquivos de log para visualização de possiveis erros!'; } else { print 'Não existem arquivos pendentes para importação!'; } ?> Compartilhar este post Link para o post Compartilhar em outros sites
mangakah 217 Denunciar post Postado Julho 21, 2012 Você não consegue importar mais por falta de memória? Tente aumentar o limite no seu arquivo php.ini ou parta o arquivo em várias partes (mas você terá que se certificar de que tanto a linha inicial quanto a final estejam inteiras nas várias partes) usando um programa específico, como o JJSplit. Compartilhar este post Link para o post Compartilhar em outros sites
sakamoto 0 Denunciar post Postado Julho 21, 2012 Então mangakah obrigado por se mostrar a ajudar... exatamente o arquivo não importa por conta de memória... já tentei aumentar o php.ini para o tamanho do arquivo para 10mb. Não posso picar o arquivo pois o cliente fará upload do arquivo a ser importado na pasta e rodará o importar_estoque.php. Minha idéia seria importar uma certa quantidade, pausar, importar mais, pausar etc... não sei se isso vai aliviar a memória... mas também nem imagino como fazê-lo. Você tem alguma outra idéia?!? Compartilhar este post Link para o post Compartilhar em outros sites
mangakah 217 Denunciar post Postado Julho 21, 2012 Então mangakah obrigado por se mostrar a ajudar... exatamente o arquivo não importa por conta de memória... já tentei aumentar o php.ini para o tamanho do arquivo para 10mb. Não posso picar o arquivo pois o cliente fará upload do arquivo a ser importado na pasta e rodará o importar_estoque.php. Minha idéia seria importar uma certa quantidade, pausar, importar mais, pausar etc... não sei se isso vai aliviar a memória... mas também nem imagino como fazê-lo. Você tem alguma outra idéia?!? Na verdade você já está usando a solução que consome menos memória. Usar fgets() faz o PHP lê o arquivo linha por linha até a conclusão, ao contrário de file_get_contents() que carrega de uma vez todo o conteúdo de um arquivo. É bom especificar o tamanho máximo de cada linha (o segundo parâmetro da fumção fgets), só porque você não especificou um não significa que não haja um limite. Verifique também o tempo máximo de execução (diretiva 'max_execution_time' no php.ini), o padrão é de apenas 30 segundos. Se possível, amplie isso também. Compartilhar este post Link para o post Compartilhar em outros sites
Bruno Augusto 417 Denunciar post Postado Julho 21, 2012 Outra coisa que pode ajudar... Você tem vários loops no mesmo arquivo logo, na mesma requisição. Se você fragmentar cada etapa em múltiplas requisições, interligando-as através de sessões, a última etapa que é a de inserir/atualizar no banco terá muitomais memória para executar. Se mesmo fragmentando dessa forma ainda não for suficiente, você pode determinar porções menores do array $IMPORTAR através de querystrings as quais preencherão os argumentos de um array_slice() Compartilhar este post Link para o post Compartilhar em outros sites
sakamoto 0 Denunciar post Postado Agosto 7, 2012 puxa obrigado pela ajuda... mas nem imagino onde inserir este "slice"... vou estudar. Obrigadaço Compartilhar este post Link para o post Compartilhar em outros sites
Bruno Augusto 417 Denunciar post Postado Agosto 7, 2012 Você não apenas inserir, vai montar uma "falsa paginação" sobre $IMPORTAR Falsa porque não haverão números a serem clicados. A "página" estará oculta, numa tag META Refresh. Informando o quarto argumento como TRUE, os índices serão preservados. O padrão é FALSE, isto é, cada nova fatia começará a contar do zero. Mantendo os índices originais, a cada nova requisição você pegaria o índice do último elemento da fatia, adicionaria +1 e montaria a tag META Refresh passando esse valor como parâmetro GET. A página seria a mesma, mas a cada nova requisição esse valor mudará, e você conseguirá controlar o argumento offset de array_slice(). Na primeira requisição você teria a fatia de 0 à 50 (exemplo). Faz o insert/update e monta a tag meta refresh com o valor 51: $importar = array_slice( $importar, $_GET['offset'], 50, TRUE ); Na segunda requisição, essa mesma linha retornará uma fatia diferente do array, agora de 51 até 101 e variável GET será 102. Na terceira requisição, teremos de 102 até 152 e variável GET será 153. E por aí vai, até acabar. Compartilhar este post Link para o post Compartilhar em outros sites