在shell脚本中调用sql语句

时间:2009-10-08 02:33:13

标签: oracle shell oracle10g ksh

我正在使用Solaris环境,而我正在使用的数据库是Oracle 10g。

我正在尝试的骷髅;

编写ksh脚本以执行以下操作。我不知道怎么做 在shell脚本中包含我的sql查询并循环遍历 声明。因此,下面给出了我正在尝试的内容的一个主旨。

  1. 复制要处理的文件(一次一个文件,从10个列表中删除 文件夹中的文件。)

    for in in * 做  cp $ i / home / temp

  2. 2。创建快照(n)表:初始化n = 1

    create table test insert account_no, balance from
    records_all; 
    

    - 创建我的快照表并插入记录 在SQL

    1. 检查表是否已成功创建:
    2. 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“从results_all中选择max(value)” - 将最大值打印到控制台

      2. 使用以下作业处理我的文件:

      3. ./runscript.ksh - READ -i $m(m - 初始值001) ./runscript.ksh - WRITE -i $m(m - 初始值001 - 与READ process_id相同)

        - 将m增加1

        1. 等待成功记录

          tail -f log($ m)* | -egrep“^ SUCCESS”

        2. 循环到第1步到: 将文件2复制到临时文件夹; 创建快照(n + 1)表

        3. 复制完所有文件进行处理后退出。

          done - 第1步结束

          让我感动的指针非常有价值。

          感谢,

          克里斯

3 个答案:

答案 0 :(得分: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列在所有表上具有相同的名称。可以修改脚本以更改这些假设,但附加数据必须来自某个地方。它可能属于输入文件,在这种情况下,您需要对读取行进行标记。

答案 1 :(得分:1)

这是一个指针:不要尝试在shell中执行此操作。你可以将这个算法运用到shell中,并且有大量的转义表达式和管道进出数据库客户端,但是它很难阅读并且难以维护。考虑使用一些脚本或编译语言(Python,Perl,R,Java,C ++)执行此任务,并对Oracle数据库进行打包支持。

答案 2 :(得分:0)

有两种选择可以实现。

  1. 创建一个sql脚本文件,并在正确建立与数据库的连接后执行
  2. 创建一个here文档,并通过连接到数据库
  3. 使用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创建一个here文档并使用sqlplus

    执行它
    print "your query;
    COMMIT;" > SQLS
    cmd='sqlplus ${ORALOGIN} < SQLS >> sachin.log
    eval $cmd