2010-11-18 17 views
5

Abbiamo uno script Perl che esegue un SQL e inserisce i dati nella tabella. Ora invece di fornire una singola istruzione SQL, vogliamo passare un gruppo di essi riunendoli in un file .sql. Sappiamo che il nostro programma fallirà perché si aspetta una singola istruzione SQL, non un gruppo di essi (anche questo da un file .sql). Come facciamo a farlo funzionare con un file .sql (con più istruzioni INSERT?). Stiamo usando il pacchetto DBI.Esegui file SQL in Perl

Un piccolo frammento di codice:

$sth = $dbh->prepare("/home/user1/tools/mytest.sql"); 
$sth->execute || warn "Couldn't execute statement"; 
$sth->finish(); 
+0

vedere anche http://stackoverflow.com/questions/945584/is-it-possible-to-execute-multiple-statements-in-a-single-query-using-dbdoracle http://stackoverflow.com/ domande/1232950/perl-dbi-run-sql-script-with-multiple-statement – daxim

risposta

4
Non

esattamente sicuro di quello che vuoi ...

Una volta creato un oggetto di DBI, si può usarlo più e più volte. Qui sto leggendo istruzione SQL dopo la dichiarazione di SQL da un file e l'elaborazione di tutti e di ciascuno, al fine di:

use DBI; 

my $sqlFile = "/home/user1/tools/mytest.sql" 

my $dbh = DBI::Connect->new($connect, $user, $password) 
    or die("Can't access db"); 

# Open the file that contains the various SQL statements 
# Assuming one SQL statement per line 

open (SQL, "$sqlFile") 
    or die("Can't open file $sqlFile for reading"); 

# Loop though the SQL file and execute each and every one. 
while (my $sqlStatement = <SQL>) { 
    $sth = dbi->prepare($sqlStatement) 
     or die("Can't prepare $sqlStatement"); 

    $sth->execute() 
     or die("Can't execute $sqlStatement"); 
} 

Si noti che sto mettendo l'istruzione SQL nel nome del file prepare e non che contiene il codice SQL dichiarazione. Potrebbe essere il tuo problema?

+0

qui sto chiamando il file dq.sql nello script perl in cui sto passando una variabile come $ nome_patch, $ svn_url, $ ftp_path che è definita nel file perl ma il file db.sql non sta accedendo a quelle variabili? pls mi aiuta subito. $ sqlfile = "C: /BuildScript/YellowBox_Script/YellowBox_Core_Script/db.sql"; open (SQL, "$ sqlfile") o die ("Impossibile aprire il file $ sqlFile per la lettura"); while ($ SQLStatement = ) { $ sth = $ dbh-> prepare ($ SQLStatement) or die ("Impossibile preparare $ SQLStatement"); $ sth-> execute() o die ("Impossibile eseguire $ sqlStatement"); } ' – picnic4u

+1

@ picnic4u: puoi creare una domanda invece di un commento? Gli altri lo vedranno e possono aiutarti. –

+0

A meno che non manchi qualcosa, ciò presuppone un'affermazione per riga, che è difficilmente garantita. –

4

Non è necessario perl per questo a tutti. Basta usare il mysql client a riga di comando:

mysql -h [hostname] -u[username] -p[password] [database name] < /home/user1/tools/mytest.sql

sostituire le variabili [] con le tue informazioni.

Nota spazio dopo -u o -p. Se il server MySQL è in esecuzione sulla stessa macchina è possibile omettere -h [hostname] (il default è localhost)

+0

Ciao Cfreak, in realtà è uno script che non ha molte altre cose, quindi abbiamo bisogno che la modifica sia questo script. Grazie per la soluzione però. – t0mcat

0

Ecco come l'ho fatto. Nel mio caso non presumo un SQL per riga e presumo, il mio esempio è un po 'meglio :)

sub get_sql_from_file { 
    open my $fh, '<', shift or die "Can't open SQL File for reading: $!"; 
    local $/; 
    return <$fh>; 
}; 

my $SQL = get_sql_from_file("SQL/file_which_holds_sql_statements.sql"); 
my $sth1 = $dbh1->prepare($SQL); 
$sth1->execute(); 
+1

Perché il 'get_sql_from_file' non restituisce l'SQL, piuttosto che impostare una variabile globale? Le variabili globali sono cattive. –

+0

Potrebbe restituire l'SQL, ma perché pensi che l'uso della variabile $ SQL sia negativo in quell'esempio? Puoi spiegarlo? volevi dire che l'uso di variabili globali è una cattiva idea in generale? –

+1

Le variabili globali sono, in generale, una cattiva idea. Le tue funzioni saranno più facili da riutilizzare se sono autonome e non presuppongono l'esistenza di variabili esterne. –

3

C'è una sorta di soluzione alternativa per DDL. È necessario innanzitutto svuotare il file SQL e quindi includerlo nel contenuto delle parole chiave BEGIN ... END;. Come:

sub exec_sql_file { 
    my ($dbh, $file) = @_; 

    my $sql = do { 
     open my $fh, '<', $file or die "Can't open $file: $!"; 
     local $/; 
     <$fh> 
    }; 

    $dbh->do("BEGIN $sql END;"); 
} 

Questa subroutine permette di eseguire DDL (SQL) script con più istruzioni all'interno del database (ad esempio discariche).