如何在 UNIX shell 脚本中执行临时存储过程?是不是可以在 sql-plus 中使用 IF-ELSE/WHILE 循环?

Posted

技术标签:

【中文标题】如何在 UNIX shell 脚本中执行临时存储过程?是不是可以在 sql-plus 中使用 IF-ELSE/WHILE 循环?【英文标题】:How to rxecute an ad-hoc stored procudure in UNIX shell script? Also is it possible to have IF-ELSE/WHILE LOOPS in sql-plus?如何在 UNIX shell 脚本中执行临时存储过程?是否可以在 sql-plus 中使用 IF-ELSE/WHILE 循环? 【发布时间】:2013-05-21 21:08:30 【问题描述】:

我有一个由以下三个部分组成的问题,源于我的以下要求。我被要求使用 shell 脚本自动化一些存储过程。之前存储过程的性质(不是定义,而是PL/SQL中的执行方式)曾经是这样的

begin
  SP_RTB_UPDATE('DECLARE v_var1;
                 begin
                   INSERT INTO TRADINGACCOUNT(TAEXTREFSEQID, TRADINGACCOUNTID,
                                              LASTUPDATEDBY, LASTUPDATEDATE,
                                              EXTERNALSYSTEMREFERENCEVALUE)
                      VALUES (SEQ_TA_EXT_REF_ID.NEXTVAL,12345,
                              9999,sysdate,
                              v_var1) 
                      RETURNING TAEXTREFSEQID INTO V_PK;

                   INSERT INTO EXTREFSTATUS( TAEXTREFSEQID, SINCEDATETIME, 
                                             STATUSID, LASTUPDATEDBY )
                     VALUES ( V_PK, SYSDATE, 54, 9999 );');
end;

所以基本上,存储过程是一个临时过程,它接受整个查询作为第一个参数。在内部,proc 运行一些审计表(连同查询)来存储维护历史记录/更改。现在,我想做的是设计一个shell脚本,可以自动存储过程而无需人工干预。

我做过类似的事情

#!/bin/bash

echo "Please enter your username"

read DBUSER

echo "Please enter your password"

read DBUSERPASSWORD

echo "Please enter the Database name"

read DBSID

sqlplus -S $DBUSER/$DBUSERPASSWORD@$DBSID <<EOF

if [ $? -eq 0 ]

then

            echo "Connection OK"

            echo "Please insert the RMS code to be added"

            read RMS

            INSERT INTO TRADINGACCOUNT(TAEXTREFSEQID,TRADINGACCOUNTID,
                                       LASTUPDATEDBY, LASTUPDATEDATE, 
                                       EXTERNALSYSTEMREFERENCEVALUE )
              VALUES (SEQ_TA_EXT_REF_ID.NEXTVAL,12345,
                      9999,sysdate,
                      '$RMS')
              RETURNING TAEXTREFSEQID INTO V_PK;

         INSERT INTO EXTREFSTATUS( TAEXTREFSEQID, SINCEDATETIME,
                                   STATUSID, LASTUPDATEDBY )
           VALUES ( V_PK, SYSDATE, 54, 9999 );

   COMMIT;

ECHO "Done Successfully"
else
 echo "Connection NOT OK"
fi

现在这段代码有很多问题。以下是我的疑问。

1.if [ $? eq 0 ].. 抛出错误为“未知命令,剩余行被忽略”。那么,是否可以在 sqlplus(unix) 语句中使用 IF-ELSE/WHILE 循环

    此外,INSERT 语句的 RETURNING INTO 选项不起作用。当我们在 UNIX(sqlplus) 中运行时,它的可能等价物是什么?

3.是否可以从脚本中调用临时存储过程,例如

execute SP_RTB_UPDATES('DECLARE v_var1....');

或者我们必须分开查询和编写额外的查询来处理审计表?但这会像存储过程一样安全吗?

请指教。提前致谢!

【问题讨论】:

【参考方案1】:

这是部分答案 - 您正在混合使用 shell 和 sqplus 命令 您创建了一个 here 文档 - 这很像直接输入 sqlplus。

if [ $? -eq 0 ]

是一个 shell 命令而不是 sqlplus。如果 sqlplus 失败,您将永远无法进入此处的文档。不要测试它是否以这种方式工作。

sqlplus usr/pwsd@instance <<-EOF

-- sqlplus DML and PL/SQL only commands in here: SELECt, UPDATE, etc.    
EOF
[ $? -ne 0 ] && echo 'failure'

同样:read RMS 在此处文档之前。

关于创建“整个命令即席”,使用 EXEC IMMEDIATE - Dynamic SQL

RMS=13
USER=foo
PSWD=foo
mycommand=$(printf "EXEC immediate 'select blah from table where blah = %s';"  "$RMS" )

sqlplus @USER/$PWSD/@instance <<-EOF
    $mycommand
EOF

以上只是示例,请在此处学习如何执行此操作,请点击动态SQL页面底部的链接:

http://docs.oracle.com/cd/B19306_01/appdev.102/b14261/executeimmediate_statement.htm

【讨论】:

感谢您的回复。有价值的输入,尤其是 sqlplus 和 unix commanline 之间的差异。谢谢!

以上是关于如何在 UNIX shell 脚本中执行临时存储过程?是不是可以在 sql-plus 中使用 IF-ELSE/WHILE 循环?的主要内容,如果未能解决你的问题,请参考以下文章

在 unix 中完成 command1 后执行 command2 的 shell 脚本

在 unix shell 中,如何将昨天的日期转换为变量?

需要在不同的unix服务器中执行shell脚本[重复]

如何在shell脚本中执行cd命令

运行shell脚本报错```$'\r':command not found```

如何在 Unix 控制台或 Mac 终端上运行 shell 脚本?