0

bash からいくつかの SQL スクリプトを実行しています。コミットを追加する前に、ORA エラーの概要を確認したいと思います。このようなもの:

#!/bin/bash
S_DB2_CONNECTOR=""
echo "My statement"
SQL_STM=$( echo "UPDATE ..." | sqlplus login/pass@bd );
echo "Output:"
echo "$SQL_STM"
echo "searching for errors...."
echo $LOG_VAR | grep "ORA"
echo "before commit"
wait 1000
echo "COMMIT;" | sqlplus -s login/pass@bd;

しかし、これは機能しません。なぜなら、sqlplus セッションが壊れており、!SURPRISE! sqlplus は、SQL_STM 実行後に自動コミットを追加しました。

コミット前にORA-/ST-エラーのsqlplus出力を解析する方法は? この端末画面が望ましいです。

たぶん、解析にbashは必要なく、sqlplusがそれを行うことができますか? (したがって、セッション状態は保持されます)。

4

1 に答える 1

1

ORAコードの場合にロールバック/追加の処理を行う場合は、すべてSQL*PLUSセッションで実行します。

つまり、スクリプトとして実行します。

set serverout on
begin
  update...;

exception
  when others -- others is a catch all, you can catch specific codes too
  then 
    rollback;
    dbms_output.put_line('Error!');
    dbms_output.put_line(sqlerrm); -- prints full error string
end;
/

sqlステートメントが失敗したことをbashに通知したいだけの場合は、sql*plusの最初のものとして設定できます。whenever sqlerror exit sql.sqlcode(またはwhenever sqlerror (exit -1など)代わりに(ここを参照)。これは最初のエラーで停止し、適切なリターンコードを使用してシェルスクリプトに戻ります。

ブロックをネストできます。例:

begin
  update ..;
  begin
    select id into v_id
      from tab
     where ...;
  exception
    when no_data_found
    then
      null;-- ignore that we didnt find a row
  end;
  -- if the select fails, we continue from here..
  delete...;
  begin
    savepoint mysave;
    your_proc(...);
  exception
   when others
   then
     rollback to mysave; -- of the call to your_proc fails, lets just toll that back alone
  end;

end;

インタラクティブにする必要がある場合は、(dbms_alert)[http://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_alert.htm#CHDCFHCI]のように実行できます。

sqlplus /<<EOF | tee -a my.log
set feedback on verify on serverout on 
-- IE YOUR CODE HERE..
select * from dual;
begin
  null;
end;
/
-- END OF YOUR CODE..
-- now lets wait for an alert from another session:
declare
  v_message  varchar2(32767);
  v_status   number;
begin
  DBMS_ALERT.REGISTER('should_i_commit');
  DBMS_ALERT.WAITONE('should_i_commit', v_message, v_status); -- there is a timeout parameter you can set too
  if (v_message = 'Y')
  then
    dbms_output.put_line('I committed');
    commit;
  else
    dbms_output.put_line('I rolled back');
    rollback;
  end if;
end;
/
EOF

次に、別のセッションで次を発行できます。

SQL> exec dbms_alert.signal('should_i_commit', 'N');

PL/SQL procedure successfully completed.

SQL> commit;

Commit complete.
于 2013-01-29T07:57:00.403 に答える