2010-01-15 16 views

risposta

15

Non esiste un modo portatile per farlo. È possibile eseguire un client nativo come un programma esterno per farlo però:

import java.io.*; 
public class CmdExec { 

    public static void main(String argv[]) { 
    try { 
     String line; 
     Process p = Runtime.getRuntime().exec 
     ("psql -U username -d dbname -h serverhost -f scripfile.sql"); 
     BufferedReader input = 
     new BufferedReader 
      (new InputStreamReader(p.getInputStream())); 
     while ((line = input.readLine()) != null) { 
     System.out.println(line); 
     } 
     input.close(); 
    } 
    catch (Exception err) { 
     err.printStackTrace(); 
    } 
    } 
} 
  • Esempio di codice è stato estratto dai here e modificato per rispondere alla domanda partendo dal presupposto che l'utente vuole eseguire un file di script di PostgreSQL.
2

No, è necessario leggere il file, dividerlo in query separate e quindi eseguirle singolarmente (o utilizzando l'API batch di JDBC).

Uno dei motivi è che ogni database definisce il proprio modo di separare le istruzioni SQL (alcuni usano ;, altri /, alcuni consentono entrambi o anche di definire il proprio separatore).

0

JDBC non supporta questa opzione (sebbene un driver DB specifico possa offrire questo). Ad ogni modo, non dovrebbe esserci un problema con il caricamento di tutti i contenuti del file in memoria.

2

Non è possibile utilizzare JDBC poiché non supporta. Il lavoro dovrebbe essere incluso iBatis iBATIS è un framework di persistenza e chiamare il costruttore Scriptrunner come mostrato nella documentazione iBatis.

La sua non è bene includere un framework di persistenza peso pesante come ibatis al fine di eseguire un semplice script SQL eventuali modi che si può fare utilizzando riga di comando

$ mysql -u root -p db_name < test.sql 
+0

ibatis suona bene per questo compito! – felipecrp

23

C'è grande modo di eseguire script SQL da Java senza leggerli da soli fino a quando non ti dispiace avere una dipendenza da Ant. A mio avviso, una tale dipendenza è molto ben giustificata nel tuo caso. Ecco il codice di esempio, dove la classe SQLExec vive in ant.jar:

private void executeSql(String sqlFilePath) { 
    final class SqlExecuter extends SQLExec { 
     public SqlExecuter() { 
      Project project = new Project(); 
      project.init(); 
      setProject(project); 
      setTaskType("sql"); 
      setTaskName("sql"); 
     } 
    } 

    SqlExecuter executer = new SqlExecuter(); 
    executer.setSrc(new File(sqlFilePath)); 
    executer.setDriver(args.getDriver()); 
    executer.setPassword(args.getPwd()); 
    executer.setUserid(args.getUser()); 
    executer.setUrl(args.getUrl()); 
    executer.execute(); 
} 
+0

Ho provato questo per alcuni dei miei script Oracle Oracle, funziona per 'insert',' create table'. Ma per lo script che ha 'create o sostituisci trigger 'fallisce con ** java.sql.SQLSyntaxErrorException: ORA-00900: istruzione SQL non valida ** –

+0

Forse dovresti considerare i tuoi delimitatori – carpinchosaurio

0

provare questo codice:

String strProc = 
     "DECLARE \n" + 
     " sys_date DATE;"+ 
     "" + 
     "BEGIN\n" + 
     "" + 
     " SELECT SYSDATE INTO sys_date FROM dual;\n" + 
     "" + 
     "END;\n"; 

try{ 
    DriverManager.registerDriver (new oracle.jdbc.driver.OracleDriver()); 
    Connection connection = DriverManager.getConnection ("jdbc:oracle:thin:@your_db_IP:1521:your_db_SID","user","password"); 
    PreparedStatement psProcToexecute = connection.prepareStatement(strProc); 
    psProcToexecute.execute(); 
}catch (Exception e) { 
    System.out.println(e.toString()); 
} 
+8

Il tuo esempio è eccessivamente semplicistico. Un 'Statement' di solito può eseguire solo una dichiarazione SQL alla volta. La domanda implica che ci siano un numero elevato di query o inserimenti coinvolti e che pertanto devono essere suddivisi in singole affermazioni trovando i separatori. – BoffinbraiN

+0

Concordato, questa soluzione non funzionerà su script multi-statement. Usa jisql come suggerito di seguito. –

1

Poiché JDBC non supporta questa opzione il modo migliore per risolvere questo problema è l'esecuzione del comando linee tramite il programma Java. Bellow è un esempio a PostgreSQL:

private void executeSqlFile() { 
    try { 
     Runtime rt = Runtime.getRuntime(); 
     String executeSqlCommand = "psql -U (user) -h (domain) -f (script_name) (dbName)"; 
     Process pr = rt.exec(); 
     int exitVal = pr.waitFor(); 
     System.out.println("Exited with error code " + exitVal); 
     } catch (Exception e) { 
     System.out.println(e.toString()); 
     } 
} 
2

biblioteca Flyway è veramente buono per questo:

Flyway flyway = new Flyway(); 
    flyway.setDataSource(dbConfig.getUrl(), dbConfig.getUsername(), dbConfig.getPassword()); 
    flyway.setLocations("classpath:db/scripts"); 
    flyway.clean(); 
    flyway.migrate(); 

Questo analizza le posizioni per gli script e li esegue in ordine. Gli script possono essere versionati con V01__name.sql, quindi se viene chiamata solo la migrazione, verranno eseguiti solo quelli non ancora eseguiti. Usa una tabella chiamata 'schema_version' per tenere traccia delle cose. Ma può fare anche altre cose, vedi i documenti: flyway.

La chiamata pulita non è necessaria, ma utile per iniziare da un DB pulito. Inoltre, sii consapevole della posizione (l'impostazione predefinita è "classpath: db/migration"), non c'è spazio dopo ":", quello mi ha sorpreso.

1

Il più semplice strumento esterno che ho trovato che sia anche portatile è jisql - https://www.xigole.com/software/jisql/jisql.jsp. Lo avresti eseguito come:

java -classpath lib/jisql.jar:\ 
      lib/jopt-simple-3.2.jar:\ 
      lib/javacsv.jar:\ 
      /home/scott/postgresql/postgresql-8.4-701.jdbc4.jar 
    com.xigole.util.sql.Jisql -user scott -password blah  \ 
    -driver postgresql          \ 
    -cstring jdbc:postgresql://localhost:5432/scott -c \; \ 
    -query "select * from test;" 
+0

Ho usato 'java -classpath lib/jisql-2.0.11.jar: lib/jopt-simple-3.2.jar: lib/javacsv.jar: ../ojdbc7.jar com.xigole.util.sql.Jisql -user ecm -password TODO -driver oracle.jdbc.OracleDriver -cstring jdbc: oracle: thin: @localhost: 1521: XE -c \; -input myoracle.sql' e ha funzionato perfettamente. –

Problemi correlati