вторник, 7 июня 2011 г.

Oracle: Выполнение команд ОС и обработка результатов

Этой теме посвещено много статей, но когда занялся сам, то встретился с трудностями получения и обработки кода ошибки (кода возврата) команды, поэтому опишу следующий вариант решения:

На просторах Интеренета (а именно здесь) нашел следующий код:
try {
 Process p = Runtime.getRuntime().exec("Команда ОС");
 BufferedReader stdInput = new BufferedReader(new
 InputStreamReader(p.getInputStream()));
 BufferedReader stdError = new BufferedReader(new
 InputStreamReader(p.getErrorStream()));
 System.out.println("Here is the standard output of the command:\n");
 while ((s = stdInput.readLine()) != null) {
  System.out.println(s);
 }
 System.out.println("Here is the standard error of the command (if any):\n");
 while ((s = stdError.readLine()) != null) {
  System.out.println(s);
 }
}
catch (IOException e) {
 System.out.println("exception happened - here's what I know:");
 e.printStackTrace();
}
Программа выполняет команду, а затем считывает стандартный выходной поток и поток ошибок.
Меня вполне все устроило, заиcключением того, что проблематично получить код ошибки, возвращаемый при завершении работы программы.
В Windows строка Runtime.getRuntime().exec("echo %errorlevel%")
всегда вернет "0" (насколько я понял, из рантайма вообще невозможно работать с переменными окружения, из за того, что в разных системах доступ к ним осуществляется по разному).

Поискав дальше нашел статью.
Т.е. код возвата программы можно получить:
System.out.println(p.exitValue());
Теперь оформим в виде хранимой процедуры Oracle:
CREATE OR REPLACE AND COMPILE JAVA SOURCE NAMED "os_execute" AS
import java.io.*;
public class os_execute {
 public static void main() throws IOException {
  String s = null;
  try {
   Process p = Runtime.getRuntime().exec("Команда ОС");
   BufferedReader stdInput = new BufferedReader(new
   InputStreamReader(p.getInputStream()));
   BufferedReader stdError = new BufferedReader(new
   InputStreamReader(p.getErrorStream()));
   System.out.println("Here is the standard output of the command:\n");
   while ((s = stdInput.readLine()) != null) {
    System.out.println(s);
   }
   System.out.println("Here is the standard error of the command (if any):\n");
   while ((s = stdError.readLine()) != null) {
    System.out.println(s);
   }
   System.out.println(p.exitValue());
  }
  catch (IOException e) {
   System.out.println("exception happened - here's what I know:");
   e.printStackTrace();
  }
 }
}
Таким образом на терминале отобразится текст, возвращаемый командной строкой, и код ошибки.
Код также будет работать и под Linux.
Данную процедуру можно переделать в функцию и возвращать результаты в выходном параметре.

воскресенье, 5 июня 2011 г.

Удаление связанных таблиц ORACLE

При необходимсоти массового удаления таблиц возникают проблемы из-за многочисленных связей между ними.
Данный скрипт решает эту проблему, удаляя сначала внешние ключи, уникальные индексы и чеккеры, затем первичные ключи, а затем и сами таблицы.

set serveroutput on;
begin
  for i in (select * from all_constraints where table_name in ('t1', 't2') and constraint_type in ('U','C','R')) loop
    dbms_output.put_line('alter table ' || i.table_name || ' drop constraint ' || i.constraint_name || ';');
  end loop;

  for i in (select * from all_constraints where table_name in ('t1', 't2') and constraint_type = 'P') loop
    dbms_output.put_line('alter table ' || i.table_name || ' drop constraint ' || i.constraint_name || ';');
  end loop;
  
  for i in (select * from all_tables where table_name in ('t1', 't2') loop
    dbms_output.put_line('drop table ' || i.table_name || ';');
  end loop;
end;