【问题标题】:Invoking sql statements in shell scripts在 shell 脚本中调用 sql 语句
【发布时间】:2010-12-04 20:29:00
【问题描述】:

我在 Solaris 环境下工作,我使用的数据库是 Oracle 10g。

我正在尝试的骨架;

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

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

    因为我在 * 做 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. 等待成功日志

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

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

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

done -- 步骤 1 结束

让我动起来的指针将非常有价值。

谢谢,

克里斯

【问题讨论】:

  • 我不明白你的问题到底是什么。您是在问如何从 shell 脚本执行 sql 语句?

标签: oracle shell oracle10g ksh


【解决方案1】:

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

【讨论】:

  • 感谢您的建议。我唯一熟悉的脚本语言是shell。感谢您是否可以在考虑到 shell 解决方案的情况下扩展您的输入。
【解决方案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 列在所有表上具有相同的名称。可以修改脚本以更改这些假设,但附加数据必须来自某个地方。它可能属于输入文件,在这种情况下,您需要对读取的行进行标记。

【讨论】:

    【解决方案3】:

    有两个选项可以实现。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-08
      • 1970-01-01
      相关资源
      最近更新 更多