2009-09-30 13 views

risposta

5

Basta leggerlo e quindi utilizzare la dichiarazione preparata con il file sql completo al suo interno.

(se ricordo bene)

ADD: Si può anche leggere e divisa su ";" e poi tutti di eseguire in un ciclo. Non dimenticare i commenti e aggiungere nuovamente la ";"

+0

Non ha funzionato. Errore generato per ";" che presenta alla fine di ogni istruzione sql. – shafi

+0

quindi rimuovere il punto e virgola - le istruzioni preparate probabilmente non prendono i delimitatori. – Chii

+0

Voto positivo per la punta divisa! –

-1

Si può leggere lo script linea per linea con un BufferedReader e aggiungere ogni linea ad un StringBuilder in modo che lo script diventa una stringa di grandi dimensioni.

Quindi è possibile creare un oggetto Statement utilizzando JDBC e chiamare statement.execute(stringBuilder.toString()).

+1

Non funziona – firstthumb

27

Questo collegamento potrebbe aiutarti: http://pastebin.com/f10584951.

incollato sotto per i posteri:

/* 
* Slightly modified version of the com.ibatis.common.jdbc.ScriptRunner class 
* from the iBATIS Apache project. Only removed dependency on Resource class 
* and a constructor 
*/ 
/* 
* Copyright 2004 Clinton Begin 
* 
* Licensed under the Apache License, Version 2.0 (the "License"); 
* you may not use this file except in compliance with the License. 
* You may obtain a copy of the License at 
* 
*  http://www.apache.org/licenses/LICENSE-2.0 
* 
* Unless required by applicable law or agreed to in writing, software 
* distributed under the License is distributed on an "AS IS" BASIS, 
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
* See the License for the specific language governing permissions and 
* limitations under the License. 
*/ 

import java.io.IOException; 
import java.io.LineNumberReader; 
import java.io.PrintWriter; 
import java.io.Reader; 
import java.sql.*; 

/** 
* Tool to run database scripts 
*/ 
public class ScriptRunner { 

    private static final String DEFAULT_DELIMITER = ";"; 

    private Connection connection; 

    private boolean stopOnError; 
    private boolean autoCommit; 

    private PrintWriter logWriter = new PrintWriter(System.out); 
    private PrintWriter errorLogWriter = new PrintWriter(System.err); 

    private String delimiter = DEFAULT_DELIMITER; 
    private boolean fullLineDelimiter = false; 

    /** 
    * Default constructor 
    */ 
    public ScriptRunner(Connection connection, boolean autoCommit, 
      boolean stopOnError) { 
     this.connection = connection; 
     this.autoCommit = autoCommit; 
     this.stopOnError = stopOnError; 
    } 

    public void setDelimiter(String delimiter, boolean fullLineDelimiter) { 
     this.delimiter = delimiter; 
     this.fullLineDelimiter = fullLineDelimiter; 
    } 

    /** 
    * Setter for logWriter property 
    * 
    * @param logWriter 
    *   - the new value of the logWriter property 
    */ 
    public void setLogWriter(PrintWriter logWriter) { 
     this.logWriter = logWriter; 
    } 

    /** 
    * Setter for errorLogWriter property 
    * 
    * @param errorLogWriter 
    *   - the new value of the errorLogWriter property 
    */ 
    public void setErrorLogWriter(PrintWriter errorLogWriter) { 
     this.errorLogWriter = errorLogWriter; 
    } 

    /** 
    * Runs an SQL script (read in using the Reader parameter) 
    * 
    * @param reader 
    *   - the source of the script 
    */ 
    public void runScript(Reader reader) throws IOException, SQLException { 
     try { 
      boolean originalAutoCommit = connection.getAutoCommit(); 
      try { 
       if (originalAutoCommit != this.autoCommit) { 
        connection.setAutoCommit(this.autoCommit); 
       } 
       runScript(connection, reader); 
      } finally { 
       connection.setAutoCommit(originalAutoCommit); 
      } 
     } catch (IOException e) { 
      throw e; 
     } catch (SQLException e) { 
      throw e; 
     } catch (Exception e) { 
      throw new RuntimeException("Error running script. Cause: " + e, e); 
     } 
    } 

    /** 
    * Runs an SQL script (read in using the Reader parameter) using the 
    * connection passed in 
    * 
    * @param conn 
    *   - the connection to use for the script 
    * @param reader 
    *   - the source of the script 
    * @throws SQLException 
    *    if any SQL errors occur 
    * @throws IOException 
    *    if there is an error reading from the Reader 
    */ 
    private void runScript(Connection conn, Reader reader) throws IOException, 
      SQLException { 
     StringBuffer command = null; 
     try { 
      LineNumberReader lineReader = new LineNumberReader(reader); 
      String line = null; 
      while ((line = lineReader.readLine()) != null) { 
       if (command == null) { 
        command = new StringBuffer(); 
       } 
       String trimmedLine = line.trim(); 
       if (trimmedLine.startsWith("--")) { 
        println(trimmedLine); 
       } else if (trimmedLine.length() < 1 
         || trimmedLine.startsWith("//")) { 
        // Do nothing 
       } else if (trimmedLine.length() < 1 
         || trimmedLine.startsWith("--")) { 
        // Do nothing 
       } else if (!fullLineDelimiter 
         && trimmedLine.endsWith(getDelimiter()) 
         || fullLineDelimiter 
         && trimmedLine.equals(getDelimiter())) { 
        command.append(line.substring(0, line 
          .lastIndexOf(getDelimiter()))); 
        command.append(" "); 
        Statement statement = conn.createStatement(); 

        println(command); 

        boolean hasResults = false; 
        if (stopOnError) { 
         hasResults = statement.execute(command.toString()); 
        } else { 
         try { 
          statement.execute(command.toString()); 
         } catch (SQLException e) { 
          e.fillInStackTrace(); 
          printlnError("Error executing: " + command); 
          printlnError(e); 
         } 
        } 

        if (autoCommit && !conn.getAutoCommit()) { 
         conn.commit(); 
        } 

        ResultSet rs = statement.getResultSet(); 
        if (hasResults && rs != null) { 
         ResultSetMetaData md = rs.getMetaData(); 
         int cols = md.getColumnCount(); 
         for (int i = 0; i < cols; i++) { 
          String name = md.getColumnLabel(i); 
          print(name + "\t"); 
         } 
         println(""); 
         while (rs.next()) { 
          for (int i = 0; i < cols; i++) { 
           String value = rs.getString(i); 
           print(value + "\t"); 
          } 
          println(""); 
         } 
        } 

        command = null; 
        try { 
         statement.close(); 
        } catch (Exception e) { 
         // Ignore to workaround a bug in Jakarta DBCP 
        } 
        Thread.yield(); 
       } else { 
        command.append(line); 
        command.append(" "); 
       } 
      } 
      if (!autoCommit) { 
       conn.commit(); 
      } 
     } catch (SQLException e) { 
      e.fillInStackTrace(); 
      printlnError("Error executing: " + command); 
      printlnError(e); 
      throw e; 
     } catch (IOException e) { 
      e.fillInStackTrace(); 
      printlnError("Error executing: " + command); 
      printlnError(e); 
      throw e; 
     } finally { 
      conn.rollback(); 
      flush(); 
     } 
    } 

    private String getDelimiter() { 
     return delimiter; 
    } 

    private void print(Object o) { 
     if (logWriter != null) { 
      System.out.print(o); 
     } 
    } 

    private void println(Object o) { 
     if (logWriter != null) { 
      logWriter.println(o); 
     } 
    } 

    private void printlnError(Object o) { 
     if (errorLogWriter != null) { 
      errorLogWriter.println(o); 
     } 
    } 

    private void flush() { 
     if (logWriter != null) { 
      logWriter.flush(); 
     } 
     if (errorLogWriter != null) { 
      errorLogWriter.flush(); 
     } 
    } 
} 
+5

Questa soluzione è utile solo per le cose di base. Ad esempio se hai un set semplice di select/update/insert statements ecc. Ma se proverai a creare una stored procedure in questo modo ... Fallirà. –

+2

Secondo Shafi, sta avendo "40 -50 sql statement" che significa che non sta avendo SP nel suo script SQL.:) –

+0

Dal momento che sto già usando Mybatis, è stato grandioso far funzionare le cose. – chotchki

2

Si dovrebbe essere in grado di analizzare il file SQL in istruzioni. E lanciare una singola dichiarazione ogni volta. Se sai che il tuo file è composto da semplici istruzioni insert/update/delete puoi usare un punto e virgola come delimitatore di istruzioni. Nel caso comune hai un compito per creare il tuo parser SQL-dialect specifico.

18

Io uso questo pezzo di codice per importare le dichiarazioni SQL creato da mysqldump:

public static void importSQL(Connection conn, InputStream in) throws SQLException 
{ 
    Scanner s = new Scanner(in); 
    s.useDelimiter("(;(\r)?\n)|(--\n)"); 
    Statement st = null; 
    try 
    { 
     st = conn.createStatement(); 
     while (s.hasNext()) 
     { 
      String line = s.next(); 
      if (line.startsWith("/*!") && line.endsWith("*/")) 
      { 
       int i = line.indexOf(' '); 
       line = line.substring(i + 1, line.length() - " */".length()); 
      } 

      if (line.trim().length() > 0) 
      { 
       st.execute(line); 
      } 
     } 
    } 
    finally 
    { 
     if (st != null) st.close(); 
    } 
} 
+0

Non è necessario creare una dichiarazione (conn.createStatement()) per ogni riga? – Leandro

+0

evidentemente non :) –

+0

Io uso 's.useDelimiter (" (; (\ r)? \ N) | ((\ r)? \ N)? (-)?. * (- (\ r)? \ n) ");' – Daniel

7

Un'altra opzione, questo non supporta i commenti, molto utile con AmaterasERD DDL di esportazione per Apache Derby:

public void executeSqlScript(Connection conn, File inputFile) { 

    // Delimiter 
    String delimiter = ";"; 

    // Create scanner 
    Scanner scanner; 
    try { 
     scanner = new Scanner(inputFile).useDelimiter(delimiter); 
    } catch (FileNotFoundException e1) { 
     e1.printStackTrace(); 
     return; 
    } 

    // Loop through the SQL file statements 
    Statement currentStatement = null; 
    while(scanner.hasNext()) { 

     // Get statement 
     String rawStatement = scanner.next() + delimiter; 
     try { 
      // Execute statement 
      currentStatement = conn.createStatement(); 
      currentStatement.execute(rawStatement); 
     } catch (SQLException e) { 
      e.printStackTrace(); 
     } finally { 
      // Release resources 
      if (currentStatement != null) { 
       try { 
        currentStatement.close(); 
       } catch (SQLException e) { 
        e.printStackTrace(); 
       } 
      } 
      currentStatement = null; 
     } 
    } 
scanner.close(); 
} 
2

Ho avuto lo stesso problema nel tentativo di eseguire uno script SQL che crea un database SQL. Cercando su google, ho trovato una classe Java scritta inizialmente da Clinton Begin che supporta i commenti (vedi http://pastebin.com/P14HsYAG). Ho modificato leggermente il file per gestire i trigger in cui si deve modificare il DELIMITER predefinito con qualcosa di diverso. Ho usato quella versione ScriptRunner (vedi http://pastebin.com/sb4bMbVv). Dal momento che una classe SQLScriptRunner (open source e gratuita) è un'utilità assolutamente necessaria, sarebbe utile avere più input dagli sviluppatori e speriamo di avere presto una versione più stabile di essa.

Problemi correlati