2010-01-15 165 views

Respuesta

15

No hay una forma portátil de hacerlo. Puede ejecutar un cliente nativo como un programa externo para hacer eso sin embargo:

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(); 
    } 
    } 
} 
  • Ejemplo de código se extrajo de here y modificado para responder a la pregunta si se asume que el usuario desea ejecutar un archivo de comandos de PostgreSQL.
2

No, debe leer el archivo, dividirlo en consultas separadas y luego ejecutarlas individualmente (o utilizando la API por lotes de JDBC).

Una de las razones es que cada base de datos define su propia forma de separar las sentencias SQL (algunas usan ;, otras , otras permiten ambas cosas o incluso definen su propio separador).

0

JDBC no es compatible con esta opción (aunque un controlador de base de datos específico puede ofrecer esto). De todos modos, no debería haber un problema al cargar todo el contenido del archivo en la memoria.

2

No se puede hacer uso de JDBC, ya que no es compatible. El trabajo sería incluir iBatis iBATIS es un marco de persistencia y llamar al constructor Scriptrunner como se muestra en la documentación iBatis.

No es bueno incluir un marco persistencia de peso pesado como ibatis con el fin de ejecutar un simple secuencias de comandos SQL cualquier manera que usted puede hacer uso de la línea de comandos

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

¡ibatis suena bien para esta tarea! – felipecrp

23

Hay gran manera de ejecutar secuencias de comandos SQL desde Java sin leerlos usted mismo, siempre y cuando no le importe tener una dependencia de Ant. En mi opinión, esa dependencia está muy bien justificada en su caso. Aquí es código de ejemplo, donde la clase SQLExec vive en 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

Intenté esto para algunos de mis scripts de Oracle SQL, funciona para 'insert',' create table'. Pero para el script que tiene 'create or replace trigger', falla con ** java.sql.SQLSyntaxErrorException: ORA-00900: instrucción SQL no válida ** –

+0

Quizás debería considerar sus delimitadores – carpinchosaurio

0

probar este código:

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

Su ejemplo es demasiado simplista. Un 'Statement' por lo general solo puede ejecutar una declaración SQL a la vez. La pregunta implica que hay un gran número de consultas o inserciones involucradas y, por lo tanto, deben dividirse en declaraciones individuales buscando los separadores. – BoffinbraiN

+0

De acuerdo, esta solución no funcionará en scripts de instrucciones múltiples. Use jisql como se sugiere a continuación. –

1

Desde JDBC no admite esta opción la mejor manera de resolver esta cuestión es la ejecución de comandos líneas a través del Programa Java. Abajo es un ejemplo para 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 de la vía migratoria es muy bueno para esto:

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

Este explora los lugares de secuencias de comandos y los ejecuta en orden. Los scripts se pueden versionar con V01__name.sql, de modo que si solo se llama a migrate, solo se ejecutarán los que no se hayan ejecutado. Utiliza una tabla llamada 'schema_version' para realizar un seguimiento de las cosas. Pero también puede hacer otras cosas, vea los documentos: flyway.

La llamada de limpieza no es necesaria, pero es útil para comenzar desde una base de datos limpia. Además, tenga en cuenta la ubicación (el valor predeterminado es "classpath: db/migration"), no hay espacio después de ':', ese me llamó la atención.

1

La herramienta externa más simple que encontré que también es portátil es jisql - https://www.xigole.com/software/jisql/jisql.jsp. Lo ejecutaría como:

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

Utilicé '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 -contraseña TODO -driver oracle.jdbc.OracleDriver -cstring jdbc: oracle: thin: @localhost: 1521: XE -c \; -input myoracle.sql' y funcionó sin problemas. –

Cuestiones relacionadas