Enquanto você pode fazer mysql
consultas / atualizações / etc em um script de shell, é muito mais fácil usar um idioma (como perl
ou python
) com um bom suporte para os dois bancos de dados e arquivos CSV.
Aqui está uma maneira de fazer isso em perl
, usando o módulo perl DBI
e os módulos DBD::CSV
e DBD::mysql
.
Ele lê cada linha do seu arquivo CSV (denominei 'updates.csv' e assumiu que o nome da coluna é phonenum
) e emite os comandos UPDATE
do SQL para a tabela users
do dbname
banco de dados no mysql. Altere dbname
para se adequar ao seu banco de dados.
NOTA: o código a seguir não foi testado, mas deve funcionar. Como não foi testado, é possível que eu tenha cometido alguns erros de digitação ou outros erros.
Eu strongmente recomendo testá-lo primeiro em uma COPY do seu banco de dados em vez de executá-lo imediatamente nos dados reais. Na verdade, é SEMPRE uma boa ideia testar seu código em uma cópia dos dados reais, não importa o que você esteja escrevendo ou em que idioma você está escrevendo.
#! /usr/bin/perl
use strict;
use DBI;
###
### variables setup
###
# DBD::CSV treats all .csv files in this dir as tables.
# i.e. this directory is the "database" and the .csv files
# are the tables in that database.
my $csv_dir = '/path/to/csv/dir';
my $csv_db = 'updates'; # corresponds to "$csv_dir/updates.csv"
my $m_db = 'dbname'; # replace with your mysql database name
my $m_user = 'username';
my $m_pass = 'password';
my $m_host = 'localhost';
my $m_port = '3306';
my $m_dsn = "DBI:mysql:database=${m_db};host=${m_host};port=${m_port}";
###
### database handle setup
###
# database handle for CSV connection
my $c_h = DBI->connect ("DBI:CSV:", undef, undef, {
f_ext => ".csv/r",
f_dir => $csv_dir,
RaiseError => 1,
}) or die "Cannot connect: $DBI::errstr";
# database handle for mysql connection
my $m_h = DBI->connect($m_dsn, $m_user, $m_pass, { PrintError => 0 });
###
### all set up, time to do some work.
###
# NOTE: this script assumes that the .csv file contains a header line with
# the field names as the first line of the file.
#
# If not, the easiest thing to do is edit it with your preferred text
# editor and add one. Otherwise, see 'man DBD::CSV' to find out how to
# specify field names.
#
# or EDIT and uncomment the following three lines of code:
#$c_h->{csv_tables}{$csv_db} = {
# col_names => [ qw(column1 phonenum column3 column4 ...) ];
#};
# prepare statement handle for csv db query using a placeholder ? for the
# column name.
my $c_sth = $c_h->prepare("select phonenum from ?");
# and execute it. later, we'll use a forech loop to read the data returned
$c_sth->execute($csv_db);
# prepare the SQL statement for the mysql db using placeholders ? for
# the values. this assumes that the column/field name is also called
# 'phonenum' in mysql. These placeholders are invaluable, they automaticaly
# quote any data that needs to be quoted (e.g. strings) while not quoting
# things that shouldn't be quoted (e.g. integers). They prevent a huge
# range of common mistakes.
#
# prepare it once, execute it multiple times with different values.
my $m_sth = $m_h->prepare('UPDATE users SET phonenum = ? WHERE phonenum = ?');
$m_h->begin_work; # begin transaction
foreach ($c_sth->fetchrow_array) {
chomp;
my $newphone = "A2B1 $_";
$m_sth = $m_sth->execute($newphone, $_);
};
$m_h->commit; # commit transaction
###
### we're done. finish the statement handles and disconnect from
### the databases.
###
$c_sth->finish;
$m_sth->finish;
$c_h->disconnect;
$m_h->disconnect;
Parece mais longo que o script shell médio, mas a maior parte do código é apenas variável e a configuração do identificador de banco de dados (e esse código de configuração pode ser reutilizado em outros scripts semelhantes). O código real que faz o trabalho é (excluindo comentários) apenas cerca de meia dúzia de linhas.