Как выполнить файл сценария SQL в Java? - PullRequest
35 голосов
/ 15 января 2010

Я хочу выполнить файл сценария SQL на Java без чтения всего содержимого файла в большой запрос и его выполнения.

Есть ли другой стандартный способ?

Ответы [ 9 ]

26 голосов
/ 16 июня 2010

Существует отличный способ выполнения сценариев SQL из Java, не читая их самостоятельно, если вы не возражаете против зависимости от Ant. На мой взгляд, такая зависимость очень хорошо оправдана в вашем случае. Вот пример кода, где класс SQLExec живет в 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();
}
19 голосов
/ 15 января 2010

Нет портативного способа сделать это.Вы можете выполнить собственный клиент как внешнюю программу, чтобы сделать это, хотя:

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();
    }
  }
}
  • Пример кода был извлечен из здесь и изменен для ответа на вопрос, предполагая, что пользователь хочетвыполнить файл сценария PostgreSQL.
5 голосов
/ 15 января 2010

Нет, вы должны прочитать файл, разделить его на отдельные запросы и затем выполнить их по отдельности (или используя пакетный API JDBC).

Одна из причин заключается в том, что каждая база данных определяет свой собственный способотдельные операторы SQL (некоторые используют ;, другие /, некоторые разрешают оба или даже определяют свой собственный разделитель).

4 голосов
/ 07 октября 2016

Библиотека Flyway действительно хороша для этого:

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

Это сканирует места для скриптов и запускает их по порядку.Версии сценариев можно указывать с помощью V01__name.sql, поэтому, если вызывается только миграция, будут выполняться только те, которые еще не запущены.Использует таблицу с именем schema_version для отслеживания вещей.Но можно сделать и другие вещи, см. Документы: flyway .

Чистый вызов не требуется, но полезен для запуска из чистой БД.Кроме того, помните о расположении (по умолчанию «classpath: db /igration»), после ':' нет пробела, который меня поймал.

3 голосов
/ 15 января 2010

Вы не можете использовать JDBC, так как он не поддерживает. Обойти это можно, включив iBatis iBATIS - это постоянная структура, которая вызывает конструктор Scriptrunner, как показано в документации iBatis .

Не очень хорошо включать среду персистентного веса, такую ​​как ibatis, для запуска простых сценариев sql любыми способами, которые вы можете сделать с помощью командной строки

$ mysql -u root -p db_name < test.sql
2 голосов
/ 07 марта 2012

Поскольку JDBC не поддерживает эту опцию, лучшим способом решения этого вопроса является выполнение командных строк через программу Java. Ниже приведен пример 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());
      }
}
1 голос
/ 17 октября 2016

Самый простой внешний инструмент, который я нашел, также переносимый - jisql - https://www.xigole.com/software/jisql/jisql.jsp. Вы бы запустили его как:

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 голосов
/ 06 декабря 2010

Попробуйте этот код:

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());  
}
0 голосов
/ 15 января 2010

JDBC не поддерживает эту опцию (хотя конкретный драйвер БД может предлагать это). В любом случае, не должно быть проблем с загрузкой всего содержимого файла в память.

...