1

私は Solaris 環境で作業しており、使用している DB は Oracle 10g です。

私が試みているもののスケルトン。

以下を実行する ksh スクリプトを作成します。SQLクエリをシェルスクリプトに含めてステートメントをループする方法がわかりません。したがって、私が試みていることの概要を以下に示します。

  1. 処理するファイルをコピーします (フォルダー内の 10 ファイルのリストから一度に 1 ファイル)。

    for i in * do cp $i /home/temp を実行します

2. スナップショット(n) テーブルを作成します: n = 1 を初期化します

create table test insert account_no, balance from
records_all; 

-- スナップショット テーブルを作成し、SQL にレコードを挿入します

  1. テーブルが正常に作成されたかどうかの確認:

select count(*) from snapshot1 -- テーブル内のレコード数を照会します -- 常に固定、たとえば 400000

if( select count(*) from snapshot(n) = 400000 )
 echo " table creation successful.. proceed to the next step "
else
 echo " problem creating table, exiting the script .. "
  1. テーブルの作成に成功すると、

    echo " select max(value) from results_all " -- 最大値をコンソールに出力

  2. 次のジョブを使用してファイルを処理します。

./runscript.ksh - READ -i $m( m - 初期値 001 ) ./runscript.ksh - WRITE -i $m( m - 初期値 001 -- READ process_id と同じ )

-- m を 1 ずつ増やします

  1. 成功ログを待つ

    テール -f ログ ($m)* | -egrep "^成功"

  2. step1 to へのループ: ファイル 2 を一時フォルダーにコピーします。スナップショット (n+1) テーブルを作成する

すべてのファイルが処理のためにコピーされたら終了します。

done -- ステップ 1 の終了

私を動かすための指針は非常に価値があります。

ありがとう、

クリス

4

3 に答える 3

2

たまたま、私は実生活で似たようなことをしたばかりです。これが純粋なSQLソリューションです。

CREATE ANY DIRECTORYまず、ディレクトリオブジェクトを作成するには、特権を持つ誰か(おそらくDBA)が必要です。

create directory load_dir as '/home/temp'
/
grant read, write on directory load_dir to <your_user>
/

次のPL/SQLブロックは、ファイルを開いて読み取ります。ファイルの各行について、テーブルを作成し、そこからカウントして、最大ID値を取得します。

declare
    fh_tabs utl_file.file_type;
    table_name varchar2(30);
    snapshot_name varchar2(30);
    stmt varchar2(4000) ;
    cnt_row pls_integer;
    cnt_tab pls_integer := 0;
    max_id pls_integer;
begin
    fh_tabs := utl_file.fopen('LOAD_DIR', 'file.name', 'R');
    << tables >>
    loop
        begin
            utl_file.get_line(fh_tabs, table_name);
            cnt_tab := cnt_tab + 1;
            snapshot_name := 'snapshot'||trim(to_char(cnt_tab));
            stmt := 'create table '||snapshot_name
                               ||' as select * from '||table_name;
            execute immediate stmt;
            execute immediate 'select count(*) from '
                               ||snapshot_name into cnt_row;
            dbms_output.put_line('New table '||snapshot_name||' has '
                               ||to_char(cnt_row)||' records.');
            execute immediate 'select max(id) from '
                               ||snapshot_name into max_id;
            dbms_output.put_line('Highest primary key = '||max_id);
        exception
            when no_data_found then
                utl_file.fclose(fh_tabs);
                dbms_output.put_line('End of file!. Tables created = '
                               ||to_char(cnt_tab));
                exit;
        end;
    end loop tables;
end;
/

ファイルにはテーブル名しか含まれておらず、スナップショットテーブルに同じ名前を付け、ID列の名前をすべてのテーブルで同じにする必要があると想定しました。スクリプトを変更してこれらの仮定を変更することはできますが、追加のデータはどこかから取得する必要があります。入力ファイルに属している可能性があります。その場合、読み取り行をトークン化する必要があります。

于 2009-10-08T08:20:49.670 に答える
1

ここにポインタがあります。シェルでこれを実行しようとしないでください。このアルゴリズムを、データベースクライアントとの間で大量にエスケープされた式とパイプを使用してシェルに組み込むことはできますが、読み取りや保守が困難になります。Oracleデータベースのパッケージサポートを備えたスクリプト言語またはコンパイル言語(Python、Perl、R、Java、C ++)を使用してこのタスクを実行することを検討してください。

于 2009-10-08T03:44:25.430 に答える
0

これには 2 つのオプションがあります。

  1. SQLスクリプトファイルを作成し、データベースへの接続が正しく確立されたら実行し、
  2. ヒアドキュメントを作成し、データベースに接続して sqlplus で実行します

1. SQL スクリプト ファイルを作成し、データベースへの接続が正しく確立されたら実行します。

sql_file=sachin.sql
cat <<!SQL > $sql_file
    select $1 from dual;
    exit;
!SQL

sysdate=`sqlplus -s $ORACLE_LOGIN  @$sql_file 2>/dev/null  `
echo $sysdate
rm $sql_file

2 ヒアドキュメントを作成し、sqlplus で実行する

print "your query;
COMMIT;" > SQLS
cmd='sqlplus ${ORALOGIN} < SQLS >> sachin.log
eval $cmd
于 2009-12-07T11:09:59.443 に答える